I´m newbie to flutter and reveice one exception about route and paginator in Flutter.
EXCEPTION CAUGHT BY GESTURE
The following assertion was thrown while handling a gesture:
Could not find a generator for route "/listadecompras" in the _MaterialAppState.
Follow a excerpt from code:
import 'package:flutter/material.dart';
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return new MaterialApp(
// ...
return new ListTile(
onTap: () {
Navigator.pushNamed(context, "/listadecompras");
},
// ...
}
class ListaDeCompras extends StatelessWidget {
#override
Widget build(BuildContext context) {
return new Scaffold(
// ...
}
}
void main() {
runApp(new MaterialApp(
home: new MyApp(),
routes: <String, WidgetBuilder>{
"/listadecompras": (BuildContext context) => new ListaDeCompras()
}
));
}
Please, someone could send some advice?
thanks in advance for your attention
Because Of instantiated two MaterialApp widgets. You need to remove the one in MyApp class and may change it to Scaffold
Example:
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return new Scaffold(
// ...
return new ListTile(
onTap: () {
Navigator.pushNamed(context, "/listadecompras");
},
// ...
}
THE PROBLEM IS YOUR CODE IS - the route is trying to resolve for the nearest MaterialApp which has no route definition. That said you should use only one MaterialApp as the root of your widget tree.
try this :
onPressed: () {
Navigator.push(
context,
new MaterialPageRoute(
builder: (context) => new ListaDeCompras(),
),
);
},
If a new file is created and you are defining a route for that new file, its better to re-run the app rather than hot reloading.It worked for me!
flutter clean and run again, is working for me.
I had a similar issue because I defined the route as '/listadecompras' and then called Navigator.pushNamed(context, "listadecompras"); without the forward slash.
It isn't probably the same scenario than this question but it shows the same error.
It happened to me, but in my case there was a single MaterialApp widget instantiated, so I wasn't able to find the cause.
I noticed that in my App, all calls to Navigator where done the same, with:
Navigator.of(context).pushNamed('/route-name');
All, except the first one, which was like this:
Navigator.pushNamed(context, '/route-name');
After changing the above line to be equal to the others (using .of(context)), the problem got solved!
Note
Until now I had no problems with navigation, it happened once tried to navigate to a new view from a dialog.
If you have only one MaterialApp, and you cannot fix this issue, try to check your navigation chain, and use the same way of calling Navigator in every place.
Bye
#aziza is the right answer
but in some miscellaneous situation
in my case
class RouteGenerator {
static Route<dynamic> generateRoute(RouteSettings settings) {
switch (settings.name) {
case '/':
MaterialPageRoute(builder: (_) => MyScaffold());
break;
case '/homechart':
MaterialPageRoute(builder: (_) => analytics());
break;
}
}
}
I forget to return keyword and IDE not showing any error. showing this kind of error.
Solution is like this :
class RouteGenerator {
static Route<dynamic> generateRoute(RouteSettings settings) {
switch (settings.name) {
case '/':
return MaterialPageRoute(builder: (_) => MyScaffold());
break;
case '/homechart':
return MaterialPageRoute(builder: (_) => analytics());
break;
}
}
}
You have instantiated two MaterialApp widget. You need to remove the one in MyApp class.
For push
Navigator.of(context).pushNamed('/screen1')
For Pop: "popAndPushNamed"
Navigator.of(context).popAndPushNamed('/screen4');
I have encountered the same error and solved by just restarting the app
In my case the error was because i deleted the route from main.dart and forgot the update the change in other files
I had the same error i don't know why flutter does that after creating a new screen but all you need is rebuild zor re-run the app again
There need to be only one MaterialApp if you have multiple MaterialApps then I would recommend to keep only one MaterialApp for your project.
I had the same problem. the problem was that I had a template and had duplicated the screens and didn't delete my materialapps after everything worked tanks a lot
I recently had the same problem any way I managed to resolve it by using Global Key
the context which I need to navigate from was the problem because it refers to a widget not a page that holds this widget so I made static GlobalKey appKey = GlobalKey();
then use it in the scaffold of the page then i can use its context from any place in the app MainPage.appKey.currentContext;
One of the solutions would be hot restarting your code.
That is because we declare the route name outside the Widget Build.
If you don't have a home property defined for your MaterialApp, you probably should have this kind of error. Please try to fill it with a Scaffold widget.
Related
I'm trying to make a card clickable and navigate to another page 'forecastWeather.dart'. But I can't seem to figure out how I can fix the error I'm getting. The error message says
Another exception was thrown: Navigator operation requested with a context that does not include a Navigator.
I'm using a TabBarView with two tabs and one contains a card which should be clickable and navigate to another page 'forecastWeather.dart'. Please help!
In order to get use navigator.push, you must pass the context of your widget and have a MaterialApp somewhere in your tree, you do both, so the code should work, but it doesn't.
The reason is simple, the context you are passing is outdated, you are first creating the context when the build method begins, at that point, there is no material app, then you add a material app, but the context already exists, so the context you are passing when calling Navigator.push(context ... has no MaterialApp.
A possible fix is to use the Builder widget to make a new context after you create the MaterialApp widget:
#override
Widget build(BuildContext context) {
// context has no material app.
return MaterialApp(
home: Builder(
builder: (context) {
// this context does have a material app and is safe to use.
return DefaultTabController( ... );
}
),
);
}
Another fix is to move the code into a new widget with it's own context:
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: MainPage(),
);
}
}
class MainPage extends StatelessWidget {
#override
Widget build(BuildContext context) {
// this context was created after the material app.
return DefaultTabController(...);
}
}
i suggest you to use get: ^4.6.1 package.
with this package you just need to use this for any navigation:
Get.to(ForecastWeather());
this package have so other features read its document here
[1]: https://pub.dev/packages/get
listen is not working. when hot reload value is updated.
Page A
#override
Widget build(BuildContext context) {
ValueNotifier<List<ProductModel>> selectNotifier = Provider.of<ValueNotifier<List<ProductModel>>>(context, listen: true);
Widget
Text('${selectNotifier.value.length}'),
Page B
InkWell(
onTap: () {
selectNotifier.value.add(selectProduct);
},
main.dart
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MultiProvider(
providers: [
ChangeNotifierProvider<ValueNotifier<List<ProductModel>>>(
create: (_) => ValueNotifier<List<ProductModel>>([]),
),
],
child: MaterialApp(
theme: CustomTheme.themeData,
onGenerateRoute: Router.generateRoute,
debugShowCheckedModeBanner: false,
),
);
}
Version
provider: ^4.1.2
Flutter Version
1.17.2
I tried below ways to fix this issue. But I don't know what is right way(best way).
1st way
After downgrade Flutter and Provider, now is working. why is that?
provider: 3.2.0
git checkout v1.12.13-hotfixes
2nd way
Or it is working this way too.//but warning on the IDE
onTap: () {
selectNotifier.value.add(selectProduct);
selectNotifier.notifyListeners(); //info: The member 'notifyListeners' can only be used within instance members of subclasses of 'package:flutter/src/foundation/change_notifier.dart'.
},
But warning disappear, after adding this ChangeNotifier,
class _viewState extends State<View> with ChangeNotifier{
and also getting error after adding ChangeNotifier
The following assertion was thrown while finalizing the widget tree:
_CartItemViewState.dispose failed to call super.dispose.
dispose() implementations must always call their superclass dispose()
method, to ensure that all the resources used by the widget are fully
released.
3rd way
I don't get any issue on this way, but I used so many ValueNotifier in my production app, so, others are not a List. I don't know how to change other types.
onTap: () {
selectNotifier.value = List.from(selectNotifier.value)..add(widget.productModel);
}
In this question, 3rd way is the correct way.
onTap: () {
selectNotifier.value = List.from(selectNotifier.value)..add(widget.productModel);
}
I am using the package flutter_bloc for state management. I want to create a search screen, and found the showSearch Flutter function, and have been having issues providing a BLoC instance to the ListView my SearchDelegate implementation creates. I finally made it work, but would like to ask what the best way of doing this is. Here is the code (excerpts, starting from a button that is placed in an AppBar within a Scaffold):
class ItemSearchButton extends StatelessWidget {
#override
Widget build(BuildContext context) {
return IconButton(
icon: Icon(Icons.search),
onPressed: () {
final itemListBloc = context.bloc<ItemListBloc>();
showSearch(
context: context,
delegate: _ItemSearchDelegate(itemListBloc),
);
},
);
}
}
class _ItemSearchDelegate extends SearchDelegate<String> {
final ItemListBloc itemListBloc;
_ItemSearchDelegate(this.itemListBloc);
// other overridden methods
#override
Widget buildSuggestions(BuildContext context) {
return BlocProvider.value(
value: itemListBloc,
child: ItemListWidget(),
);
}
}
Basically, the context that invokes the showSearch method has the correct BLoC instance, but it is not available within my SearchDelegate implementation, unless I re-provide it again explicitly in buildSuggestions.
Why is the BLoC not available by default? The showSearch function internally pushes a new Navigator Route, is this the issue?
What is the canonical way of dealing with things like this?
Yes, when the route changes, buildContextchanges too. So you have to provide that bloc to the new context. Just wrap your page where you want to navigate with BlocProvider:
Navigator.push(context, MaterialPageRoute(builder: (BuildContext context) =>
BlocProvider(create: Mybloc(),child:MyPage());
In the end it works as intended - the pushed route has a new context that is not a child of a context that has my BLoC, it is a child of the Navigator. The solution is to either do what I did initially - pass the BLoC explicitly as constructor argument - or make sure the Navigator context has the BLoCs, which is what I eventually did; to do this, make sure the Navigator is a child of the (Multi)BlocProvider.
I tried passing data from a filter page to the home page, but keep getting the following error.
Error message on console - NoSuchMethodError being caused by widget within MaterialPageRoute()
//Radio button values to select user's gender on Filter Page
enum PrayditatorGender { Female, Male }
PrayditatorGender pGender;
//Radio button values to select Prayditation category on Filter Page
enum PrayditationFilter {
All,
Family,
Fellowship,
GodlyWisdom,
GoodSuccess,
HealthAndSafety,
}
PrayditationFilter pFilter = PrayditationFilter.All;
//Code to push the data from Filter Page to Home Page
Navigator.push(context, MaterialPageRoute(
builder: (context) {
PrayditatorHomePage(
pGender: pGender,
pFilter: pFilter
)
));
//Code to handle the data on Home Page
class PrayditatorHomePage extends StatefulWidget {
final PrayditatorGender pGender;
final PrayditationFilter pFilter;
PrayditatorHomePage({this.pGender, this.pFilter});
#override
_PrayditatorHomePageState createState() => _PrayditatorHomePageState();
}
class _PrayditatorHomePageState extends State<PrayditatorHomePage> {
#override
Widget build(BuildContext context) {}
Your syntax is wrong, you're not supposed to be having this issue, this code worked with no issues:
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => PrayditatorHomePage(
pGender: pGender,
pFilter: pFilter,
),
),
);
Thank you all for taking time to view/comment. Bug has been busted and code working effectively!
Syntax was all correct, however, a static parameter was inappropriately put in the place meant for a dynamic parameter. After all, lessons learned.
My objective is to create a method that would take the arguments of the buildcontext and screen reference and rout it accordingly with the provided details. My partially in complete code as bellow. help would much appreciate.
My Helper class
import 'package:flutter/material.dart';
class Utils {
static routToPage <T> (BuildContext context, <T> page){
Navigator.of(context).push(MaterialPageRoute(builder: (context) =>page);
}
}
The class I wants to access it
import './utils'
import 'package:flutter/material.dart';
class Home extends StatelessWidget {
navigateToPage(){
Utils.rout(BuildContext context, PageTwo())
}
}
For now as the syntax are wrong I'm stuck with my approach.
Well, I think no need to create static class. Here is a working example.
Paste the below method in a dart file.
void navigateToScreen(BuildContext context, Widget widget) {
Navigator.of(context).push(MaterialPageRoute(
builder: (_) => widget,
));
}
And use the class for navigating, like
navigateToScreen(buildContext, YourNavigationScreen());
I prefer using Widget as a object parameter instead of <T>.
Also you can check the easiest way navigate to another page by using route like this.
Create Route in (yourproject)/lib/route/routes.dart
import './page/main_page.dart';
import './page/one_page.dart';
import './page/two_page.dart';
final routes = {
'/': (BuildContext context) => MainPage(),
'/pageone': (BuildContext context) => PageOne(),
'/pagetwo': (BuildContext context) => PageTwo(),
}
Main Page in (yourproject)/lib/main.dart
import './route/routes.dart';
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
SystemChrome.setEnabledSystemUIOverlays([]);
return MaterialApp(
initialRoute: '/', // the default route is MainPage()
routes: routes,
);
}
}
When navigating to other page you can simply use either one of these Navigator.pushNamed, Navigator.popAndPushNamed, Navigator.pushNamedAndRemoveUntil, Navigator.pushReplacementNamed do like this
// your can simple change the route of your choice by changing the name of route
Navigator.pushNamed(context, '/pageone');
Navigator.popAndPushNamed(context, '/pagetwo');
...