The following _CastError was thrown building FutureBuilder<WebViewController> - flutter

I made program using flutter webview
I have error with _FutureBuilderState<WebViewController
What I want to do make the reload button as FloatingActionButton
I guess this error is relevant with future async function, but I am not sure where to fix.
══╡ EXCEPTION CAUGHT BY WIDGETS LIBRARY ╞═══════════════════════════════════════════════════════════
The following _CastError was thrown building FutureBuilder<WebViewController>(dirty, state:
_FutureBuilderState<WebViewController>#54b59):
Null check operator used on a null value
The relevant error-causing widget was:
FutureBuilder<WebViewController>
FutureBuilder:file:///Users/whitebear/MyCode/httproot/guessdrawing_flutter/lib/main.dart:305:12
When the exception was thrown, this was the stack:
#0 NavigationControls.build.<anonymous closure> (package:flutterweb/main.dart:311:59)
#1 _FutureBuilderState.build (package:flutter/src/widgets/async.dart:782:55)
#2 StatefulElement.build (package:flutter/src/widgets/framework.dart:4782:27)
#3 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4665:15)
#4 StatefulElement.performRebuild (package:flutter/src/widgets/framework.dart:4840:11)
#5 Element.rebuild (package:flutter/src/widgets/framework.dart:4355:5)
#6 ComponentElement._firstBuild (package:flutter/src/widgets/framework.dart:4643:5)
#7 StatefulElement._firstBuild (package:flutter/src/widgets/framework.dart:4831:11)
#8 ComponentElement.mount (package:flutter/src/widgets/framework.dart:4638:5)
... Normal element mounting (29 frames)
#37 Element.inflateWidget (package:flutter/src/widgets/framework.dart:3673:14)
#38 MultiChildRenderObjectElement.inflateWidget (package:flutter/src/widgets/framework.dart:6333:36)
#39 MultiChildRenderObjectElement.mount (package:flutter/src/widgets/framework.dart:6344:32)
... Normal element mounting (21 frames)
#60 Element.inflateWidget (package:flutter/src/widgets/framework.dart:3673:14)
#61 MultiChildRenderObjectElement.inflateWidget (package:flutter/src/widgets/framework.dart:6333:36)
#62 MultiChildRenderObjectElement.mount (package:flutter/src/widgets/framework.dart:6344:32)
... Normal element mounting (116 frames)
#178 Element.inflateWidget (package:flutter/src/widgets/framework.dart:3673:14)
#179 MultiChildRenderObjectElement.inflateWidget (package:flutter/src/widgets/framework.dart:6333:36)
#180 MultiChildRenderObjectElement.mount (package:flutter/src/widgets/framework.dart:6344:32)
... Normal element mounting (173 frames)
#353 Element.inflateWidget (package:flutter/src/widgets/framework.dart:3673:14)
#354 MultiChildRenderObjectElement.inflateWidget (package:flutter/src/widgets/framework.dart:6333:36)
#355 MultiChildRenderObjectElement.mount (package:flutter/src/widgets/framework.dart:6344:32)
... Normal element mounting (371 frames)
#726 Element.inflateWidget (package:flutter/src/widgets/framework.dart:3673:14)
#727 Element.updateChild (package:flutter/src/widgets/framework.dart:3425:18)
#728 RenderObjectToWidgetElement._rebuild (package:flutter/src/widgets/binding.dart:1198:16)
#729 RenderObjectToWidgetElement.mount (package:flutter/src/widgets/binding.dart:1167:5)
#730 RenderObjectToWidgetAdapter.attachToRenderTree.<anonymous closure> (package:flutter/src/widgets/binding.dart:1112:18)
#731 BuildOwner.buildScope (package:flutter/src/widgets/framework.dart:2573:19)
#732 RenderObjectToWidgetAdapter.attachToRenderTree (package:flutter/src/widgets/binding.dart:1111:13)
#733 WidgetsBinding.attachRootWidget (package:flutter/src/widgets/binding.dart:944:7)
#734 WidgetsBinding.scheduleAttachRootWidget.<anonymous closure> (package:flutter/src/widgets/binding.dart:924:7)
(elided 11 frames from class _RawReceivePortImpl, class _Timer, dart:async, and dart:async-patch)
my code is here.
class NavigationControls extends StatelessWidget {
const NavigationControls(this._webViewControllerFuture)
: assert(_webViewControllerFuture != null);
final Future<WebViewController> _webViewControllerFuture;
#override
Widget build(BuildContext context) {
return FutureBuilder<WebViewController>(
future: _webViewControllerFuture,
builder:
(BuildContext context, AsyncSnapshot<WebViewController> snapshot) {
final bool webViewReady =
snapshot.connectionState == ConnectionState.done;
final WebViewController controller = snapshot.data!;
//return IconButton(
return FloatingActionButton(
child: const Icon(Icons.replay),
onPressed: !webViewReady
? null
: () {
controller.reload();
},
);
},
);
}
NavigationControls is called here.
class WebViewExample extends StatefulWidget {
#override
_WebViewExampleState createState() => _WebViewExampleState();
}
class _WebViewExampleState extends State<WebViewExample> {
final Completer<WebViewController> _controller =
Completer<WebViewController>();
#override
void initState() {
super.initState();
if (Platform.isAndroid) WebView.platform = SurfaceAndroidWebView();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text(''),iew.
backgroundColor: Colors.white.withOpacity(0.0),
elevation: 0.0,
),
extendBodyBehindAppBar:true,
body: Builder(builder: (BuildContext context) {
return WebView(
javascriptMode: JavascriptMode.unrestricted,
onWebViewCreated: (WebViewController webViewController) {
_controller.complete(webViewController);
webViewController.loadUrl(
'https://example.com',
);
},
onProgress: (int progress) {
print("WebView is loading (progress : $progress%)");
},
javascriptChannels: <JavascriptChannel>{
_toasterJavascriptChannel(context),
},
navigationDelegate: (NavigationRequest request) {
if (request.url.startsWith('https://www.youtube.com/')) {
print('blocking navigation to $request}');
return NavigationDecision.prevent;
}
print('allowing navigation to $request');
return NavigationDecision.navigate;
},
onPageStarted: (String url) {
print('Page started loading: $url');
},
onPageFinished: (String url) {
print('Page finished loading: $url');
},
gestureNavigationEnabled: true,
);
}),
floatingActionButton:NavigationControls(_controller.future),
);
}
JavascriptChannel _toasterJavascriptChannel(BuildContext context) {
return JavascriptChannel(
name: 'Toaster',
onMessageReceived: (JavascriptMessage message) {
// ignore: deprecated_member_use
Scaffold.of(context).showSnackBar(
SnackBar(content: Text(message.message)),
);
});
}
}

The error is exactly at main.dart:305:12.
The only null check operator I can see in your code is:
final WebViewController controller = snapshot.data!;
So try changing your FAB to something like:
final bool webViewReady =
snapshot.connectionState == ConnectionState.done;
return FloatingActionButton(
child: const Icon(Icons.replay),
onPressed: !webViewReady
? null
: () {
snapshot.data!.reload();
},
This way you are not casting the type as non null before its used

Related

passing a function to from one stateful widget to another

I need to pass a function from one stateful widget to another.
Parent widget::
the function that I am passing is the following
void _setJobAddress(jobAddress) {
setState(() {
_jobAddress = jobAddress;
});
}
here is the button that opens the new view, this is how I am passing the function
TextButton(
onPressed: () => {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) =>
SearchLocationScreen(_setJobAddress)))
}
this is a little bit of the child view where I need to call the function::
class SearchLocationScreen extends StatefulWidget {
const SearchLocationScreen({Key? key}) : super(key: key);
#override
State<SearchLocationScreen> createState() => _SearchLocationScreenState();
}
class _SearchLocationScreenState extends State<SearchLocationScreen> {
Function setJobAddess; // i tried adding this, but its not working
_SearchLocationScreenState(this.setJobAddess); // i tried adding this, but its not working
List<AutocompletePrediction> placePredictions = [];
How can I make this work so that when I click a button on the child widget, the parent function passed is called?
I tried the following:
class SearchLocationScreen extends StatefulWidget {
const SearchLocationScreen(
this.setJobAddess, {
Key? key,
}) : super(key: key);
final setJobAddess;
#override
State<SearchLocationScreen> createState() => _SearchLocationScreenState();
}
class _SearchLocationScreenState extends State<SearchLocationScreen> {
//Function setJobAddess;
//_SearchLocationScreenState(this.setJobAddess);
List<AutocompletePrediction> placePredictions = [];
#override
void initState() {
widget.setJobAddess();
}
... a bunch of code that is not of importance goes here
Padding(
padding: const EdgeInsets.all(defaultPadding),
child: ElevatedButton.icon(
onPressed: () async {
print('setting job location');
widget.setJobAddess('TEXT');
Navigator.pop(context);
},
icon: Icon(Icons.home),
label: const Text("Set job location"),
style: ElevatedButton.styleFrom(
backgroundColor: secondaryColor10LightTheme,
foregroundColor: textColorLightTheme,
elevation: 0,
fixedSize: const Size(double.infinity, 40),
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(10)),
),
),
),
),
I got the following error::
════════ Exception caught by widgets library ═══════════════════════════════════
The following NoSuchMethodError was thrown building Builder:
Closure call with mismatched arguments: function '_CreateUpdateJobViewState._setJobAddress'
Receiver: Closure: (dynamic) => void from Function '_setJobAddress#43263735':.
Tried calling: _CreateUpdateJobViewState._setJobAddress()
Found: _CreateUpdateJobViewState._setJobAddress(dynamic) => void
The relevant error-causing widget was
MaterialApp
lib/main.dart:20
When the exception was thrown, this was the stack
#0 Object.noSuchMethod (dart:core-patch/object_patch.dart:38:5)
#1 _objectNoSuchMethod (dart:core-patch/object_patch.dart:85:9)
#2 _SearchLocationScreenState.initState
package:ijob_clone_app/…/location/location_search_screen.dart:26
#3 StatefulElement._firstBuild
package:flutter/…/widgets/framework.dart:5015
#4 ComponentElement.mount
package:flutter/…/widgets/framework.dart:4853
... Normal element mounting (275 frames)
#279 Element.inflateWidget
package:flutter/…/widgets/framework.dart:3863
#280 MultiChildRenderObjectElement.inflateWidget
package:flutter/…/widgets/framework.dart:6435
#281 Element.updateChild
package:flutter/…/widgets/framework.dart:3592
#282 RenderObjectElement.updateChildren
package:flutter/…/widgets/framework.dart:5964
#283 MultiChildRenderObjectElement.update
package:flutter/…/widgets/framework.dart:6460
#284 Element.updateChild
package:flutter/…/widgets/framework.dart:3570
#285 ComponentElement.performRebuild
package:flutter/…/widgets/framework.dart:4904
#286 StatefulElement.performRebuild
package:flutter/…/widgets/framework.dart:5050
#287 Element.rebuild
package:flutter/…/widgets/framework.dart:4604
#288 StatefulElement.update
package:flutter/…/widgets/framework.dart:5082
#289 Element.updateChild
package:flutter/…/widgets/framework.dart:3570
#290 ComponentElement.performRebuild
package:flutter/…/widgets/framework.dart:4904
#291 Element.rebuild
package:flutter/…/widgets/framework.dart:4604
#292 ProxyElement.update
package:flutter/…/widgets/framework.dart:5228
#293 Element.updateChild
package:flutter/…/widgets/framework.dart:3570
#294 ComponentElement.performRebuild
package:flutter/…/widgets/framework.dart:4904
#295 Element.rebuild
package:flutter/…/widgets/framework.dart:4604
#296 ProxyElement.update
package:flutter/…/widgets/framework.dart:5228
#297 _InheritedNotifierElement.update
package:flutter/…/widgets/inherited_notifier.dart:107
#298 Element.updateChild
package:flutter/…/widgets/framework.dart:3570
#299 SingleChildRenderObjectElement.update
package:flutter/…/widgets/framework.dart:6307
#300 Element.updateChild
package:flutter/…/widgets/framework.dart:3570
#301 ComponentElement.performRebuild
package:flutter/…/widgets/framework.dart:4904
#302 StatefulElement.performRebuild
package:flutter/…/widgets/framework.dart:5050
#303 Element.rebuild
package:flutter/…/widgets/framework.dart:4604
#304 StatefulElement.update
package:flutter/…/widgets/framework.dart:5082
#305 Element.updateChild
package:flutter/…/widgets/framework.dart:3570
#306 SingleChildRenderObjectElement.update
package:flutter/…/widgets/framework.dart:6307
#307 Element.updateChild
package:flutter/…/widgets/framework.dart:3570
#308 SingleChildRenderObjectElement.update
package:flutter/…/widgets/framework.dart:6307
#309 Element.updateChild
package:flutter/…/widgets/framework.dart:3570
#310 ComponentElement.performRebuild
package:flutter/…/widgets/framework.dart:4904
#311 Element.rebuild
package:flutter/…/widgets/framework.dart:4604
#312 ProxyElement.update
package:flutter/…/widgets/framework.dart:5228
#313 Element.updateChild
package:flutter/…/widgets/framework.dart:3570
#314 ComponentElement.performRebuild
package:flutter/…/widgets/framework.dart:4904
#315 StatefulElement.performRebuild
package:flutter/…/widgets/framework.dart:5050
#316 Element.rebuild
package:flutter/…/widgets/framework.dart:4604
#317 BuildOwner.buildScope
package:flutter/…/widgets/framework.dart:2667
#318 WidgetsBinding.drawFrame
package:flutter/…/widgets/binding.dart:882
#319 RendererBinding._handlePersistentFrameCallback
package:flutter/…/rendering/binding.dart:378
#320 SchedulerBinding._invokeFrameCallback
package:flutter/…/scheduler/binding.dart:1175
#321 SchedulerBinding.handleDrawFrame
package:flutter/…/scheduler/binding.dart:1104
#322 SchedulerBinding._handleDrawFrame
package:flutter/…/scheduler/binding.dart:1015
#323 _invoke (dart:ui/hooks.dart:148:13)
#324 PlatformDispatcher._drawFrame (dart:ui/platform_dispatcher.dart:318:5)
#325 _drawFrame (dart:ui/hooks.dart:115:31)
════════════════════════════════════════════════════════════════════════════════
D/EGL_emulation(15747): app_time_stats: avg=25.04ms min=14.73ms max=497.29ms count=59
D/TrafficStats(15747): tagSocket(145) with statsTag=0xffffffff, statsUid=-1
D/TrafficStats(15747): tagSocket(121) with statsTag=0xffffffff, statsUid=-1
with this you can pass it and get it from the constructor.
class SearchLocationScreen extends StatefulWidget {
const SearchLocationScreen(this.setJobAddess,{Key? key, }) : super(key: key);
final setJobAddess;
#override
State<SearchLocationScreen> createState() => _SearchLocationScreenState();
}
class _SearchLocationScreenState extends State<SearchLocationScreen> {
/*now you can use call it with like this */
#override
void initState() {
widget.setJobAddess();
}
List<AutocompletePrediction> placePredictions = [];
// your other code
the StatefulWidget gives you the possibility to get properties from the constructor, and to access that property from the State class you need just to use widget.setJobAddess();
this is what worked for me
TextButton(
onPressed: () => {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => SearchLocationScreen(
setJobAddress: _setJobAddress)))
},
child: Text(_jobAddress),
),
child widget::
class SearchLocationScreen extends StatefulWidget {
final Function setJobAddress;
const SearchLocationScreen({Key? key, required this.setJobAddress})
: super(key: key);
#override
State<SearchLocationScreen> createState() => _SearchLocationScreenState();
}
class _SearchLocationScreenState extends State<SearchLocationScreen> {
List<AutocompletePrediction> placePredictions = [];
#override
...
Expanded(
child: ListView.builder(
itemCount: placePredictions.length,
itemBuilder: ((context, index) => LocationListTile(
press: () {
widget
.setJobAddress(placePredictions[index].description);
Navigator.pop(context);
},
location: placePredictions[index].description!,
))),
),

Flutter/dart:: Adding a new field to class causing an error

I added a new field to the class CloudNote, now I am getting an error!
I am getting the error when the app is trying to display a list.
Here is all my code without adding the field :: https://github.com/casas1010/flutter_firebase_vendor_management
I know its a simple issue, but I have tried to troubleshoot this for like an hour and have not made any progress
CloudNote class::
import 'package:cloud_firestore/cloud_firestore.dart';
import '/services/cloud/cloud_storage_constants.dart';
import 'package:flutter/foundation.dart';
/*
https://youtu.be/VPvVD8t02U8?t=87934
*/
#immutable
class CloudNote {
final String documentId;
final String jobCreatorId;
final String jobDescription;
final String jobState; // I added this
const CloudNote({
required this.documentId,
required this.jobCreatorId,
required this.jobDescription,
required this.jobState, // I added this
});
// acts as constructor
CloudNote.fromSnapshot(QueryDocumentSnapshot<Map<String, dynamic>> snapshot)
: documentId = snapshot.id,
jobCreatorId = snapshot.data()[jobCreatorIdColumn],
jobState = snapshot.data()[jobStateColumn], // I added this
jobDescription = snapshot.data()[jobDescriptionColumn] as String;
}
notes view ::
import 'package:flutter/material.dart';
import '/constants/routes.dart';
import '/enums/menu_action.dart';
import '/services/auth/auth_service.dart';
import '/services/cloud/cloud_note.dart';
import '/services/cloud/firebase_cloud_storage.dart';
import '/utilities/dialogs/logout_dialog.dart';
import '/views/notes/notes_list_view.dart';
class NotesView extends StatefulWidget {
const NotesView({Key? key}) : super(key: key);
#override
_NotesViewState createState() => _NotesViewState();
}
class _NotesViewState extends State<NotesView> {
late final FirebaseCloudStorage _notesService;
String get userId => AuthService.firebase().currentUser!.id;
#override
void initState() {
_notesService = FirebaseCloudStorage();
super.initState();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Your jobs'),
actions: [
IconButton(
onPressed: () {
Navigator.of(context).pushNamed(createOrUpdateNoteRoute);
},
icon: const Icon(Icons.add),
),
PopupMenuButton<MenuAction>(
onSelected: (value) async {
switch (value) {
case MenuAction.logout:
final shouldLogout = await showLogOutDialog(context);
if (shouldLogout) {
await AuthService.firebase().logOut();
Navigator.of(context).pushNamedAndRemoveUntil(
loginRoute,
(_) => false,
);
}
}
},
itemBuilder: (context) {
return const [
PopupMenuItem<MenuAction>(
value: MenuAction.logout,
child: Text('Log out'),
),
];
},
)
],
),
body: StreamBuilder(
stream: _notesService.allNotes(jobCreatorId: userId),
builder: (context, snapshot) {
switch (snapshot.connectionState) {
case ConnectionState.waiting:
case ConnectionState.active:
if (snapshot.hasData) {
final allNotes = snapshot.data as Iterable<CloudNote>;
return NotesListView(
notes: allNotes,
onDeleteNote: (note) async {
await _notesService.deleteNote(documentId: note.documentId);
},
onTap: (note) {
Navigator.of(context).pushNamed(
createOrUpdateNoteRoute,
arguments: note,
);
},
);
} else {
return const CircularProgressIndicator();
}
default:
return const CircularProgressIndicator();
}
},
),
);
}
}
Error
The following _TypeError was thrown building NotesListView(dirty):
type 'Null' is not a subtype of type 'String'
The relevant error-causing widget was
NotesListView
lib/…/notes/notes_view.dart:72
When the exception was thrown, this was the stack
#0 new CloudNote.fromSnapshot
package:ijob_clone_app/…/cloud/cloud_note.dart:26
#1 FirebaseCloudStorage.allNotes.<anonymous closure>.<anonymous closure>
package:ijob_clone_app/…/cloud/firebase_cloud_storage.dart:39
#2 MappedListIterable.elementAt (dart:_internal/iterable.dart:413:31)
#3 ListIterator.moveNext (dart:_internal/iterable.dart:342:26)
#4 WhereIterator.moveNext (dart:_internal/iterable.dart:438:22)
#5 Iterable.length (dart:core/iterable.dart:497:15)
#6 NotesListView.build
package:ijob_clone_app/…/notes/notes_list_view.dart:26
#7 StatelessElement.build
package:flutter/…/widgets/framework.dart:4949
#8 ComponentElement.performRebuild
package:flutter/…/widgets/framework.dart:4878
#9 Element.rebuild
package:flutter/…/widgets/framework.dart:4604
#10 ComponentElement._firstBuild
package:flutter/…/widgets/framework.dart:4859
#11 ComponentElement.mount
package:flutter/…/widgets/framework.dart:4853
#12 Element.inflateWidget
package:flutter/…/widgets/framework.dart:3863
#13 Element.updateChild
package:flutter/…/widgets/framework.dart:3586
#14 ComponentElement.performRebuild
package:flutter/…/widgets/framework.dart:4904
#15 StatefulElement.performRebuild
package:flutter/…/widgets/framework.dart:5050
#16 Element.rebuild
package:flutter/…/widgets/framework.dart:4604
#17 BuildOwner.buildScope
package:flutter/…/widgets/framework.dart:2667
#18 WidgetsBinding.drawFrame
package:flutter/…/widgets/binding.dart:882
#19 RendererBinding._handlePersistentFrameCallback
package:flutter/…/rendering/binding.dart:378
#20 SchedulerBinding._invokeFrameCallback
package:flutter/…/scheduler/binding.dart:1175
#21 SchedulerBinding.handleDrawFrame
package:flutter/…/scheduler/binding.dart:1104
#22 SchedulerBinding._handleDrawFrame
package:flutter/…/scheduler/binding.dart:1015
#23 _invoke (dart:ui/hooks.dart:148:13)
#24 PlatformDispatcher._drawFrame (dart:ui/platform_dispatcher.dart:318:5)
#25 _drawFrame (dart:ui/hooks.dart:115:31)
════════════════════════════════════════════════════════════════════════════════
NotesListView ::
import 'package:flutter/material.dart';
import '/services/cloud/cloud_note.dart';
import '/utilities/dialogs/delete_dialog.dart';
/*
source: https://www.youtube.com/watch?v=VPvVD8t02U8&t=59608s
class creation :: 22:02:54
*/
typedef NoteCallback = void Function(CloudNote note);
class NotesListView extends StatelessWidget {
final Iterable<CloudNote> notes; // list of notes
final NoteCallback onDeleteNote;
final NoteCallback onTap;
const NotesListView({
Key? key,
required this.notes,
required this.onDeleteNote,
required this.onTap,
}) : super(key: key);
#override
Widget build(BuildContext context) {
return ListView.builder(
itemCount: notes.length,
itemBuilder: (context, index) {
final note =
notes.elementAt(index); // current note whose data we are returning
return ListTile(
onTap: () {
onTap(note);
},
title: Text(
note.jobDescription,
maxLines: 1,
softWrap: true,
overflow: TextOverflow.ellipsis,
),
trailing: IconButton(
onPressed: () async {
final shouldDelete = await showDeleteDialog(context);
if (shouldDelete) {
onDeleteNote(note);
}
},
icon: const Icon(Icons.delete),
),
);
},
);
}
}
This happens if you forget to update your Firestore entries. Atleast one of your CloudNote entries in Firestore does not have the field jobState. That's why Firestore returns a Null value. But it tries to map to String which leads to an exception.
Make sure to rerun the project.
or
flutter clean
and then
flutter run

Bottom navigation bar stopped working ScrollController attached to multiple scroll views pagecontroller.jumpTo error

'package:flutter/src/widgets/scroll_controller.dart': Failed assertion: line 113 pos 12: '_positions.length == 1': ScrollController attached to multiple scroll views.
After that error bottom navigation bar stop changing the current page's of pageview.
PageController pageController;
class MainController extends StatefulWidget {
#override
_MainControllerState createState() => _MainControllerState();
}
class _MainControllerState extends State<MainController>
with TickerProviderStateMixin {
#override
void initState() {
// TODO: implement initState
super.initState();
pageController = PageController(initialPage: 0, keepPage: true);
}
#override
void dispose() {
// TODO: implement dispose
super.dispose();
pageController.dispose();
}
PagesList() {
return BlocBuilder<BottomnavbarcubitCubit, BottomnavbarcubitState>(
builder: (context, state) {
return Scaffold(
body: PageView(
allowImplicitScrolling: true,
controller: pageController,
onPageChanged: (int index) => state.currentIndex = index,
children: [
NotificationsScreen(),
NotificationsScreen(),
NotificationsScreen(),
NotificationsScreen(),
],
),
bottomNavigationBar: NormalNavBar(),
);
},
);
}
}
Bottomnavbar's onTap func that creates error
try {
if (pageController.hasClients)
await pageController.animateToPage(state.currentIndex,
duration: Duration(milliseconds: 500),
curve: Curves.elasticOut);
} catch (err) {
print(err);
}
E/flutter (30081): #18 GestureBinding._handlePointerEvent
package:flutter/…/gestures/binding.dart:295
E/flutter (30081): #19 GestureBinding._flushPointerEventQueue
package:flutter/…/gestures/binding.dart:240
E/flutter (30081): #20 GestureBinding._handlePointerDataPacket
package:flutter/…/gestures/binding.dart:213
E/flutter (30081): #21 _rootRunUnary (dart:async/zone.dart:1206:13)
E/flutter (30081): #22 _CustomZone.runUnary (dart:async/zone.dart:1100:19)
E/flutter (30081): #23 _CustomZone.runUnaryGuarded (dart:async/zone.dart:1005:7)
E/flutter (30081): #24 _invoke1 (dart:ui/hooks.dart:265:10)
E/flutter (30081): #25 _dispatchPointerDataPacket (dart:ui/hooks.dart:174:5)
It occurs when the data fetching from firestore is cancelled. Then bottom navigation bar not work until restart app.

Error with IBM Visual Recognition Classification with Flutter

I am trying to take an image and send it to IBM Watson to classify it into one of 3 custom classifiers. Below is all my code.
import 'dart:io';
import 'package:camera/camera.dart';
import 'package:flutter/material.dart';
import 'package:flutter_ibm_watson/flutter_ibm_watson.dart';
import 'package:ibm_visual_recog_img_file/connection.dart';
import 'package:ourearth2020/screens/Community.dart';
import 'package:path/path.dart';
import 'dart:async';
import 'package:image_picker/image_picker.dart';
import 'package:flutter_speed_dial/flutter_speed_dial.dart';
import 'package:path_provider/path_provider.dart';
class VisualPage extends StatefulWidget {
#override
_VisualPageState createState() => _VisualPageState();
}
class _VisualPageState extends State<VisualPage> {
CameraController _controller;
List cameras;
String path;
var galleryImage;
CameraDescription cameraDescription;
Future initCamera() async {
cameras = await availableCameras();
var frontCamera = cameras.first;
_controller = CameraController(frontCamera, ResolutionPreset.high);
try {
await _controller.initialize();
} catch (e) {}
print('Controller Is Init:' + _controller.value.isInitialized.toString());
displayPreview();
}
bool displayPreview() {
if (_controller == null || !_controller.value.isInitialized) {
return false;
} else {
return true;
}
}
Future getImageFromGallery() async {
var image = await ImagePicker.pickImage(source: ImageSource.gallery);
setState(() {
galleryImage = image;
});
print('GALLERY IMAGE' + galleryImage.toString());
return galleryImage;
}
#override
void dispose() {
// Dispose of the controller when the widget is disposed.
_controller.dispose();
super.dispose();
}
#override
void initState() {
super.initState();
print('Running');
initCamera();
}
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.white,
body: Stack(children: [
displayPreview()
? AspectRatio(
aspectRatio: MediaQuery.of(context).size.width /
MediaQuery.of(context).size.height,
child: CameraPreview(_controller),
)
: Container(
child: CircularProgressIndicator(
valueColor: AlwaysStoppedAnimation<Color>(Colors.yellow),
),
),
Positioned(
top: MediaQuery.of(context).size.height - 120,
child: GestureDetector(
onTap: () async {
await getImageFromGallery();
Navigator.push(context, MaterialPageRoute(builder: (context) =>
DisplayPicture(image: galleryImage)
));
},
child: Icon(
Icons.image,
color: Colors.white,
size: 60,
)),
),
Positioned(
top: MediaQuery.of(context).size.height - 120,
left: MediaQuery.of(context).size.width / 2.2,
child: GestureDetector(
behavior: HitTestBehavior.translucent,
child: Container(
child: Icon(
Icons.camera,
color: Colors.white,
size: 60,
)),
onTap: () async {
final path = (await getTemporaryDirectory()).path +
'${DateTime.now()}.png';
try {
await _controller.takePicture(path);
Navigator.push(
context,
MaterialPageRoute(
builder: (context) =>
DisplayPicture(imagePath: path)));
} catch (e) {
print('EEEE' + e);
}
}))
]));
}
}
class DisplayPicture extends StatelessWidget {
String imagePath;
File image;
String _text;
// File file = File(imagePath)
DisplayPicture({this.imagePath, this.image});
visualImageClassifier(File image) async{
IamOptions options = await IamOptions(iamApiKey: "NRDjngCby2d-pSHOPyWQJxhuB6vOY2uOTCX6KV2BCfwB", url: "https://api.us-south.visual-recognition.watson.cloud.ibm.com/instances/ef286f4e-84c7-44e0-b63d-a6a49a142a30").build();
VisualRecognition visualRecognition = new VisualRecognition(iamOptions: options, language: Language.ENGLISH); // Language.ENGLISH is language response
ClassifiedImages classifiedImages = await visualRecognition.classifyImageFile(image.path);
print(classifiedImages.getImages()[0].getClassifiers()[0]
.getClasses()[0]
.className);
// print("${image.toString()}");
// print('ACCESS'+options.accessToken);
//print(options);
//print("${image.path}");
//print('CLASSIFICATION'+classifiedImages.customClasses.toString()); // StreamBuilder(
// stream: StreamMyClassifier(
// image,
// 'NRDjngCby2d-pSHOPyWQJxhuB6vOY2uOTCX6KV2BCfwB', 'CompostxLandfillxRecycle_2056123069'),
// builder: (context, snapshot) {
// if (snapshot.hasData) {
// _text = snapshot.data;
// print(_text);
// }
// else {
// print('NO DATA AVAILABLE');
// }
//
// }
// );
}
#override
Widget build(BuildContext context) {
return Scaffold(body:Stack(children:[Center(child:image==null?Image.file(File(imagePath)):Image.file(image)),Positioned(
top: MediaQuery.of(context).size.height/2,
child: FloatingActionButton(onPressed:() async{
await visualImageClassifier(image==null?File(imagePath):image);
},
child:Icon(Icons.arrow_right)),
)]));
}
}
The image is successfully displayed on my screen but once I send it through the visualRecognition.classifyImageFile(....); it gives me an error saying I can not use image because it only supports String. I converted it to String but it gives me the error below.
[ERROR:flutter/lib/ui/ui_dart_state.cc(166)] Unhandled Exception: FileSystemException: Cannot retrieve length of file, path = 'File: '/data/user/0/com.example.ourearth2020/cache2020-09-17 18:50:16.530957.png'' (OS Error: No such file or directory, errno = 2)
E/flutter (17606): #0 _File.length.<anonymous closure> (dart:io/file_impl.dart:366:9)
E/flutter (17606): #1 _rootRunUnary (dart:async/zone.dart:1198:47)
E/flutter (17606): #2 _CustomZone.runUnary (dart:async/zone.dart:1100:19)
E/flutter (17606): #3 _FutureListener.handleValue (dart:async/future_impl.dart:143:18)
E/flutter (17606): #4 Future._propagateToListeners.handleValueCallback (dart:async/future_impl.dart:696:45)
E/flutter (17606): #5 Future._propagateToListeners (dart:async/future_impl.dart:725:32)
E/flutter (17606): #6 Future._completeWithValue (dart:async/future_impl.dart:529:5)
E/flutter (17606): #7 Future._asyncCompleteWithValue.<anonymous closure> (dart:async/future_impl.dart:567:7)
E/flutter (17606): #8 _rootRun (dart:async/zone.dart:1190:13)
E/flutter (17606): #9 _CustomZone.run (dart:async/zone.dart:1093:19)
E/flutter (17606): #10 _CustomZone.runGuarded (dart:async/zone.dart:997:7)
E/flutter (17606): #11 _CustomZone.bindCallbackGuarded.<anonymous closure> (dart:async/zone.dart:1037:23)
E/flutter (17606): #12 _microtaskLoop (dart:async/schedule_microtask.dart:41:21)
E/flutter (17606): #13 _startMicrotaskLoop (dart:async/schedule_microtask.dart:50:5)
E/flutter (17606):
Some of the questions I have: Can I get the confidence score using this? The last time I tried using those statements to classify the image it used a general classifier(if I input an image of a skyscraper it told me skyscraper) so how can I have it classify with my 3 classifiers?
Btw I already set up the IBM Cloud and it is fully functional. The library that I found from pub.dev is here https://pub.dev/packages/flutter_ibm_watson
EDIT error code for getImages() method
[ERROR:flutter/lib/ui/ui_dart_state.cc(166)] Unhandled Exception: NoSuchMethodError: The method 'getImages' was called on null.
E/flutter (31403): Receiver: null
E/flutter (31403): Tried calling: getImages()
E/flutter (31403): #0 Object.noSuchMethod (dart:core-patch/object_patch.dart:51:5)
E/flutter (31403): #1 DisplayPicture.visualImageClassifier (package:ourearth2020/screens/VisualPage.dart:147:30)
E/flutter (31403): <asynchronous suspension>
E/flutter (31403): #2 DisplayPicture.build.<anonymous closure> (package:ourearth2020/screens/VisualPage.dart:177:15)
E/flutter (31403): #3 _InkResponseState._handleTap (package:flutter/src/material/ink_well.dart:992:19)
E/flutter (31403): #4 _InkResponseState.build.<anonymous closure> (package:flutter/src/material/ink_well.dart:1098:38)
E/flutter (31403): #5 GestureRecognizer.invokeCallback (package:flutter/src/gestures/recognizer.dart:184:24)
E/flutter (31403): #6 TapGestureRecognizer.handleTapUp (package:flutter/src/gestures/tap.dart:524:11)
E/flutter (31403): #7 BaseTapGestureRecognizer._checkUp (package:flutter/src/gestures/tap.dart:284:5)
E/flutter (31403): #8 BaseTapGestureRecognizer.handlePrimaryPointer (package:flutter/src/gestures/tap.dart:219:7)
E/flutter (31403): #9 PrimaryPointerGestureRecognizer.handleEvent (package:flutter/src/gestures/recognizer.dart:477:9)
E/flutter (31403): #10 PointerRouter._dispatch (package:flutter/src/gestures/pointer_router.dart:78:12)
E/flutter (31403): #11 PointerRouter._dispatchEventToRoutes.<anonymous closure> (package:flutter/src/gestures/pointer_router.dart:124:9)
E/flutter (31403): #12 _LinkedHashMapMixin.forEach (dart:collection-patch/compact_hash.dart:377:8)
E/flutter (31403): #13 PointerRouter._dispatchEventToRoutes (package:flutter/src/gestures/pointer_router.dart:122:18)
E/flutter (31403): #14 PointerRouter.route (package:flutter/src/gestures/pointer_router.dart:108:7)
E/flutter (31403): #15 GestureBinding.handleEvent (package:flutter/src/gestures/binding.dart:220:19)
E/flutter (31403): #16 GestureBinding.dispatchEvent (package:flutter/src/gestures/binding.dart:200:22)
E/flutter (31403): #17 GestureBinding._handlePointerEvent (package:flutter/src/gestures/binding.dart:158:7)
E/flutter (31403): #18 GestureBinding._flushPointerEventQueue (package:flutter/src/gestures/binding.dart:104:7)
E/flutter (31403): #19 GestureBinding._handlePointerDataPacket (package:flutter/src/gestures/binding.dart:88:7)
E/flutter (31403): #20 _rootRunUnary (dart:async/zone.dart:1206:13)
E/flutter (31403): #21 _CustomZone.runUnary (dart:async/zone.dart:1100:19)
E/flutter (31403): #22 _CustomZone.runUnaryGuarded (dart:async/zone.dart:1005:7)
E/flutter (31403): #23 _invoke1 (dart:ui/hooks.dart:283:10)
E/flutter (31403): #24 _dispatchPointerDataPacket (dart:ui/hooks.dart:192:5)
E/flutter (31403):
You can copy past run full code below
You can see confidence score in working demo below
please change image.toString() to image.path because image is File
from
ClassifiedImages classifiedImages = await visualRecognition.classifyImageFile(image.toString());
to
ClassifiedImages classifiedImages = await visualRecognition.classifyImageFile(image.path);
working demo
working demo 2 for CameraPreview
I/flutter (31132): living room
full code
import 'package:camera/camera.dart';
import 'package:flutter/material.dart';
import 'dart:io';
import 'package:flutter_ibm_watson/flutter_ibm_watson.dart';
import 'package:image_picker/image_picker.dart';
import 'package:path_provider/path_provider.dart';
class VisualPage extends StatefulWidget {
#override
_VisualPageState createState() => _VisualPageState();
}
class _VisualPageState extends State<VisualPage> {
CameraController _controller;
List cameras;
String path;
var galleryImage;
CameraDescription cameraDescription;
Future initCamera() async {
cameras = await availableCameras();
var frontCamera = cameras.first;
_controller = CameraController(frontCamera, ResolutionPreset.high);
try {
await _controller.initialize();
} catch (e) {}
print('Controller Is Init:' + _controller.value.isInitialized.toString());
displayPreview();
setState(() {});
}
bool displayPreview() {
if (_controller == null || !_controller.value.isInitialized) {
return false;
} else {
return true;
}
}
Future getImageFromGallery() async {
var image = await ImagePicker.pickImage(source: ImageSource.gallery);
setState(() {
galleryImage = image;
});
print('GALLERY IMAGE' + galleryImage.toString());
return galleryImage;
}
#override
void dispose() {
// Dispose of the controller when the widget is disposed.
_controller.dispose();
super.dispose();
}
#override
void initState() {
super.initState();
print('Running');
initCamera();
}
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.white,
body: Stack(children: [
displayPreview()
? AspectRatio(
aspectRatio: MediaQuery.of(context).size.width /
MediaQuery.of(context).size.height,
child: CameraPreview(_controller),
)
: Container(
child: CircularProgressIndicator(
valueColor: AlwaysStoppedAnimation<Color>(Colors.yellow),
),
),
Positioned(
top: MediaQuery.of(context).size.height - 120,
child: GestureDetector(
onTap: () async {
await getImageFromGallery();
Navigator.push(
context,
MaterialPageRoute(
builder: (context) =>
DisplayPicture(image: galleryImage)));
},
child: Icon(
Icons.image,
color: Colors.white,
size: 60,
)),
),
Positioned(
top: MediaQuery.of(context).size.height - 120,
left: MediaQuery.of(context).size.width / 2.2,
child: GestureDetector(
behavior: HitTestBehavior.translucent,
child: Container(
child: Icon(
Icons.camera,
color: Colors.white,
size: 60,
)),
onTap: () async {
final path = (await getTemporaryDirectory()).path +
'${DateTime.now()}.png';
try {
await _controller.takePicture(path);
Navigator.push(
context,
MaterialPageRoute(
builder: (context) =>
DisplayPicture(imagePath: path)));
} catch (e) {
print('EEEE' + e);
}
}))
]));
}
}
class DisplayPicture extends StatelessWidget {
String imagePath;
File image;
String _text;
// File file = File(imagePath)
DisplayPicture({this.imagePath, this.image});
visualImageClassifier(File image) async {
IamOptions options = await IamOptions(
iamApiKey: "NRDjngCby2d-pSHOPyWQJxhuB6vOY2uOTCX6KV2BCfwB",
url:
"https://api.us-south.visual-recognition.watson.cloud.ibm.com/instances/ef286f4e-84c7-44e0-b63d-a6a49a142a30")
.build();
VisualRecognition visualRecognition = new VisualRecognition(
iamOptions: options,
language: Language.ENGLISH); // Language.ENGLISH is language response
ClassifiedImages classifiedImages =
await visualRecognition.classifyImageFile(image.path);
print(classifiedImages
.getImages()[0]
.getClassifiers()[0]
.getClasses()[0]
.className);
// print("${image.toString()}");
// print('ACCESS'+options.accessToken);
//print(options);
//print("${image.path}");
//print('CLASSIFICATION'+classifiedImages.customClasses.toString()); // StreamBuilder(
// stream: StreamMyClassifier(
// image,
// 'NRDjngCby2d-pSHOPyWQJxhuB6vOY2uOTCX6KV2BCfwB', 'CompostxLandfillxRecycle_2056123069'),
// builder: (context, snapshot) {
// if (snapshot.hasData) {
// _text = snapshot.data;
// print(_text);
// }
// else {
// print('NO DATA AVAILABLE');
// }
//
// }
// );
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: Stack(children: [
Center(
child:
image == null ? Image.file(File(imagePath)) : Image.file(image)),
Positioned(
top: MediaQuery.of(context).size.height / 2,
child: FloatingActionButton(
onPressed: () async {
await visualImageClassifier(
image == null ? File(imagePath) : image);
},
child: Icon(Icons.arrow_right)),
)
]));
}
}
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: VisualPage(),
);
}
}

Flutter: Routing to widgets from a Drawer

Is there an example on how to create a draw app & reuse widgets occupying the screen? Yes I know there is an example in the gallery demo app. However that's a bit cheeky because that sample doesn't actually replace, set or change route to a different widget.
I've tried a the new instance of a widget from the onTap event of the drawer item. I've tried having my Getting duplicate global key errors when creating new instances of those widgets when an item is selected from the drawer and the old/new route is pop/pushed
ScheduleHomeWidget scheduleWidget = new ScheduleHomeWidget(onSendFeedback: widget.onSendFeedback,);
SpeakerListWidget speakerWidget = new SpeakerListWidget();
var routes = <String, WidgetBuilder> {
ScheduleHomeWidget.routeName : (BuildContext context) => scheduleWidget,
SpeakerListWidget.routeName : (BuildContext context) => speakerWidget
};
and my MaterialApp:
return new MaterialApp(
title: kAppTitle,
routes: routes,
home: scheduleWidget,
);
and the code to launch the new route:
onTap: () {
if (routeName != null) {
Timeline.instantSync('Start Transition', arguments: <String, String>{
'from': '/',
'to': routeName
});
Navigator.pop(context);
Navigator.pushNamed(context, routeName);
}
}
}
I'm not specifying a key when instantiating either the ScheduleHomeWidget or the SpeakerListWidget instantiation. That said, the ScheduleHomeWidget uses an AnimatedList which does use a GlobalKey<AnimatedListState>
I'll see the following exception:
══╡ EXCEPTION CAUGHT BY WIDGETS LIBRARY ╞═══════════════════════════════════════════════════════════
The following assertion was thrown building Flexible(flex: 1):
Multiple widgets used the same GlobalKey.
The key [LabeledGlobalKey<AnimatedListState>#d63d7] was used by multiple widgets. The parents of
those widgets were different widgets that both had the following description:
Flexible(flex: 1)
A GlobalKey can only be specified on one widget at a time in the widget tree.
When the exception was thrown, this was the stack:
#0 GlobalKey._debugReserveFor.<anonymous closure> (package:flutter/src/widgets/framework.dart:238:9)
#2 GlobalKey._debugReserveFor (package:flutter/src/widgets/framework.dart:219:12)
#3 Element.updateChild.<anonymous closure> (package:flutter/src/widgets/framework.dart:2524:13)
#5 Element.updateChild (package:flutter/src/widgets/framework.dart:2521:12)
#6 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:3403:16)
#7 Element.rebuild (package:flutter/src/widgets/framework.dart:3292:5)
#8 ProxyElement.update (package:flutter/src/widgets/framework.dart:3639:5)
#9 Element.updateChild (package:flutter/src/widgets/framework.dart:2542:15)
#10 RenderObjectElement.updateChildren (package:flutter/src/widgets/framework.dart:4066:32)
#11 MultiChildRenderObjectElement.update (package:flutter/src/widgets/framework.dart:4448:17)
#12 Element.updateChild (package:flutter/src/widgets/framework.dart:2542:15)
#13 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:3403:16)
#14 Element.rebuild (package:flutter/src/widgets/framework.dart:3292:5)
#15 ProxyElement.update (package:flutter/src/widgets/framework.dart:3639:5)
#16 Element.updateChild (package:flutter/src/widgets/framework.dart:2542:15)
#17 RenderObjectElement.updateChildren (package:flutter/src/widgets/framework.dart:4066:32)
#18 MultiChildRenderObjectElement.update (package:flutter/src/widgets/framework.dart:4448:17)
#19 Element.updateChild (package:flutter/src/widgets/framework.dart:2542:15)
#20 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:3403:16)
#21 Element.rebuild (package:flutter/src/widgets/framework.dart:3292:5)
#22 ProxyElement.update (package:flutter/src/widgets/framework.dart:3639:5)
#23 Element.updateChild (package:flutter/src/widgets/framework.dart:2542:15)
#24 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:3403:16)
#25 Element.rebuild (package:flutter/src/widgets/framework.dart:3292:5)
#26 StatefulElement.update (package:flutter/src/widgets/framework.dart:3528:5)
#27 Element.updateChild (package:flutter/src/widgets/framework.dart:2542:15)
#28 SingleChildRenderObjectElement.update (package:flutter/src/widgets/framework.dart:4340:14)
#29 Element.updateChild (package:flutter/src/widgets/framework.dart:2542:15)
#30 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:3403:16)
#31 Element.rebuild (package:flutter/src/widgets/framework.dart:3292:5)
#32 StatelessElement.update (package:flutter/src/widgets/framework.dart:3453:5)
#33 Element.updateChild (package:flutter/src/widgets/framework.dart:2542:15)
#34 SingleChildRenderObjectElement.update (package:flutter/src/widgets/framework.dart:4340:14)
#35 Element.updateChild (package:flutter/src/widgets/framework.dart:2542:15)
#36 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:3403:16)
#37 Element.rebuild (package:flutter/src/widgets/framework.dart:3292:5)
#38 StatefulElement.update (package:flutter/src/widgets/framework.dart:3528:5)
#39 Element.updateChild (package:flutter/src/widgets/framework.dart:2542:15)
#40 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:3403:16)
#41 Element.rebuild (package:flutter/src/widgets/framework.dart:3292:5)
#42 StatefulElement.update (package:flutter/src/widgets/framework.dart:3528:5)
#43 Element.updateChild (package:flutter/src/widgets/framework.dart:2542:15)
#44 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:3403:16)
#45 Element.rebuild (package:flutter/src/widgets/framework.dart:3292:5)
#46 ProxyElement.update (package:flutter/src/widgets/framework.dart:3639:5)
#47 Element.updateChild (package:flutter/src/widgets/framework.dart:2542:15)
#48 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:3403:16)
#49 Element.rebuild (package:flutter/src/widgets/framework.dart:3292:5)
#50 ProxyElement.update (package:flutter/src/widgets/framework.dart:3639:5)
#51 Element.updateChild (package:flutter/src/widgets/framework.dart:2542:15)
#52 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:3403:16)
#53 Element.rebuild (package:flutter/src/widgets/framework.dart:3292:5)
#54 StatefulElement.update (package:flutter/src/widgets/framework.dart:3528:5)
#55 Element.updateChild (package:flutter/src/widgets/framework.dart:2542:15)
#56 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:3403:16)
#57 Element.rebuild (package:flutter/src/widgets/framework.dart:3292:5)
#58 BuildOwner.buildScope (package:flutter/src/widgets/framework.dart:2142:33)
#59 BindingBase&SchedulerBinding&GestureBinding&ServicesBinding&RendererBinding&WidgetsBinding.drawFrame (package:flutter/src/widgets/binding.dart:503:20)
#60 BindingBase&SchedulerBinding&GestureBinding&ServicesBinding&RendererBinding._handlePersistentFrameCallback (package:flutter/src/rendering/binding.dart:189:5)
#61 BindingBase&SchedulerBinding._invokeFrameCallback (package:flutter/src/scheduler/binding.dart:688:15)
#62 BindingBase&SchedulerBinding.handleDrawFrame (package:flutter/src/scheduler/binding.dart:636:9)
#63 BindingBase&SchedulerBinding&GestureBinding&ServicesBinding&RendererBinding.scheduleWarmUpFrame.<anonymous closure> (package:flutter/src/rendering/binding.dart:275:20)
#65 _Timer._runTimers (dart:isolate-patch/timer_impl.dart:366)
#66 _Timer._handleMessage (dart:isolate-patch/timer_impl.dart:394)
#67 _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:151)
(elided 3 frames from class _AssertionError and package dart:async-patch)
════════════════════════════════════════════════════════════════════════════════════════════════════
Reloaded 9 of 459 libraries in 2,143ms.
Another exception was thrown: 'package:flutter/src/widgets/framework.dart': Failed assertion: line 3727 pos 14: '_dependents.isEmpty': is not true.
Another exception was thrown: 'package:flutter/src/widgets/framework.dart': Failed assertion: line 1662 pos 12: '_elements.contains(element)': is not true.`
This error looks like Flutter is trying to add a widget to the tree by it's ID more than once. Not really trying to do that. Just looking to have two widgets that can take the main focus of the screen. Don't necessarily have to be created a new each time a user selects from the side bar.
What you can do here is add a Navigator on home. With this setup, you can manage the navigation with a Navigator key.
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
drawer: Drawer(
child: ListView(
children: _drawer(),
),
),
body: Navigator(
key: _navigatorKey, // use a Navigator key so the app won't be confused when managing routes
initialRoute: Nemo.pageA, // Set default page
...
),
);
}
The Navigator returns the Widget builder of the selected tab.
Navigator(
key: _navigatorKey, // use a Navigator key so the app won't be confused when managing routes
initialRoute: Nemo.pageA, // Set default page
onGenerateRoute: (RouteSettings settings) {
WidgetBuilder builder;
_currentPage = settings.name;
// Depending on the route name pushed
// set the Widget builder to be returned by the Navigator
// if pushed route is non-existent, return a 404 page
switch (settings.name) {
case Nemo.pageA:
builder = (BuildContext context) => const Center(child: Text('Page A'));
break;
case Nemo.pageB:
builder = (BuildContext context) => const Center(child: Text('Page B'));
break;
case Nemo.pageC:
builder = (BuildContext context) => const Center(child: Text('Page C'));
break;
default:
builder = (BuildContext context) => const Center(child: Text('404'));
}
return MaterialPageRoute(
builder: builder,
settings: settings,
);
},
),
On your drawer, you can push the route when the tab has been tapped. Check if the tab tapped is the current page displayed on screen so the same page won't be pushed by the Navigator again.
List<Widget> _drawer() {
return <Widget>[
ListTile(
title: const Text('Page A'),
onTap: () {
Navigator.pop(context);
if (_currentPage != Nemo.pageA) {
_navigatorKey.currentState!
.pushNamedAndRemoveUntil(Nemo.pageA, (Route route) => false);
}
},
),
...
];
}
Complete sample
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class Nemo {
static const String pageA = '/pageA';
static const String pageB = '/pageB';
static const String pageC = '/pageC';
}
class MyHomePage extends StatefulWidget {
const MyHomePage({Key? key, required this.title}) : super(key: key);
final String title;
#override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
final _navigatorKey = GlobalKey<NavigatorState>();
String? _currentPage;
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
drawer: Drawer(
child: ListView(
children: _drawer(),
),
),
body: Navigator(
key:
_navigatorKey, // use a Navigator key so the app won't be confused when managing routes
initialRoute: Nemo.pageA, // Set default page
onGenerateRoute: (RouteSettings settings) {
WidgetBuilder builder;
_currentPage = settings.name;
// Depending on the route name pushed
// set the Widget builder to be returned by the Navigator
// if pushed route is non-existent, return a 404 page
switch (settings.name) {
case Nemo.pageA:
builder =
(BuildContext context) => const Center(child: Text('Page A'));
break;
case Nemo.pageB:
builder =
(BuildContext context) => const Center(child: Text('Page B'));
break;
case Nemo.pageC:
builder =
(BuildContext context) => const Center(child: Text('Page C'));
break;
default:
builder =
(BuildContext context) => const Center(child: Text('404'));
}
return MaterialPageRoute(
builder: builder,
settings: settings,
);
},
),
);
}
List<Widget> _drawer() {
return <Widget>[
ListTile(
title: const Text('Page A'),
onTap: () {
Navigator.pop(context);
if (_currentPage != Nemo.pageA) {
_navigatorKey.currentState!
.pushNamedAndRemoveUntil(Nemo.pageA, (Route route) => false);
}
},
),
ListTile(
title: const Text('Page B'),
onTap: () {
Navigator.pop(context);
if (_currentPage != Nemo.pageB) {
_navigatorKey.currentState!
.pushNamedAndRemoveUntil(Nemo.pageB, (Route route) => false);
}
},
),
ListTile(
title: const Text('Page C'),
onTap: () {
Navigator.pop(context);
if (_currentPage != Nemo.pageC) {
_navigatorKey.currentState!
.pushNamedAndRemoveUntil(Nemo.pageC, (Route route) => false);
}
},
),
];
}
}