Extract routes into separate dart files - flutter

I have a list of routes with more than 50 lines and I wish to simplify it because it is very long and messy. Below is the example of current routes. Is there anyway I can extract it into separate files? For example, put //2 in routes2.dart file and //3 in routes3.dart file? How do I call them back in MyApp?
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MultiProvider(
providers: [
ChangeNotifierProvider( create: (_) => SettingsNotifier()),
ChangeNotifierProvider(create: (_) => InterstitialTimerNotifier()),
ChangeNotifierProvider(create: (_) => InterstitialReadyNotifier()),
ChangeNotifierProvider(create: (_) => PolicyNotifier()),
],
child: MaterialApp(
themeMode:ThemeMode.system,
theme: ThemeClass.lightTheme,
darkTheme: ThemeClass.darkTheme,
initialRoute: HomeScreen.id,
routes: {
//1. Home
HomeScreen.id: (context) => HomeScreen(),
//2. Puasa
PuasaScreen.id: (context) => PuasaScreen(),
DoaBerbuka.id: (context) => DoaBerbuka(),
NiatPuasa.id: (context) => NiatPuasa(),
WaktuMustajabDoa.id: (context) => WaktuMustajabDoa(),
PuasaPengenalanScreen.id: (context) => PuasaPengenalanScreen(),
PuasaReference.id: (context) => PuasaReference(),
//3. Solat Tarawih
TarawihScreen.id: (context) => TarawihScreen(),
TarawihPengenalanScreen.id: (context) => TarawihPengenalanScreen(),
TarawihNiat.id:(context) => TarawihNiat(),
TarawihTakrif.id: (context) => TarawihTakrif(),
TarawihDalilScreen.id: (context) => TarawihDalilScreen(),
TarawihHukum.id: (context) => TarawihHukum(),
TarawihReference.id: (context) => TarawihReference(),
TarawihWaktuSolat.id: (context) => TarawihWaktuSolat(),
TarawihKelebihanScreen.id: (context) => TarawihKelebihanScreen(),
TarawihBilanganRakaat.id: (context) => TarawihBilanganRakaat(),
Tarawih8Screen.id: (context) => Tarawih8Screen(),
Tarawih8TatacaraScreen.id: (context) => Tarawih8TatacaraScreen(),
//4. Solat Witir
Tarawih8WitirScreen.id: (context) => Tarawih8WitirScreen(),
Tarawih8WitirRakaat1.id: (context) => Tarawih8WitirRakaat1(),
Tarawih8WitirRakaat2.id: (context) => Tarawih8WitirRakaat2(),
Tarawih8WitirRakaat3.id: (context) => Tarawih8WitirRakaat3(),
TarawihTahlil.id: (context) => TarawihTahlil(),
//There're more routes after this
}),
);
}
}

routes: takes Map<String, WidgetBuilder>, you can create
a dart file and create a map like,
final Map<String, WidgetBuilder> route2 = {
PuasaScreen.id: (context) => PuasaScreen(),
.....
};
same goes for routes3.dart.
and you can add theses routes on MaterialApp like
return MaterialApp(
routes: {
HomeScreen.id: (context) => HomeScreen(),
...route2, /// variable name
...route3,
},
);

This is the updated code after applying suggestions from #OMiShah.
I created new dart files for the routes. For example, route_puasa.dart:
import ...
Map routes_puasa = {
PuasaScreen.id: (context) => PuasaScreen(),
DoaBerbuka.id: (context) => DoaBerbuka(),
NiatPuasa.id: (context) => NiatPuasa(),
WaktuMustajabDoa.id: (context) => WaktuMustajabDoa(),
PuasaPengenalanScreen.id: (context) => PuasaPengenalanScreen(),
PuasaReference.id: (context) => PuasaReference(),
};
Then call it in MyApp using ... Spread Operator
routes: {
...routes_puasa,
...route_tarawih,
...routes_tarawih20,
...routes_zakat,
}
Works perfectly!

Related

I have been running an andriod simulation . this is has been my error every time

I have this graduation project . I converted my figma to flutter(dart). I have running an andriod simulation on intelli jetbrains. however i keep getting this error :
"Could not find a generator for route RouteSettings("/", null) in the _WidgetsAppStat
If u can help me out it would be greatly appreciated.
This is the code if u could help it would be really great. I am trying to see if my figma design is being implemented properly. I have been running a hundred of times.
The full main.dart code is posted below:
void main() {
runApp(Covid_19_20AppApp());
}
class Covid_19_20AppApp extends StatelessWidget {
get generateRoute => null;
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Covid-19',
theme: ThemeData(
primarySwatch: Colors.blue,
),
initialRoute: '/GeneratedAndroid1Widget',
onGenerateRoute:generateRoute,
routes: {
'/GeneratedAndroid5Widget': (context) => GeneratedAndroid5Widget(),
'/GeneratedAndroid13Widget': (context) => GeneratedAndroid13Widget(),
'/GeneratedAndroid16Widget': (context) => GeneratedAndroid16Widget(),
'/GeneratedAndroid20Widget': (context) => GeneratedAndroid20Widget(),
'/GeneratedAndroid23Widget': (context) => GeneratedAndroid23Widget(),
'/GeneratedAndroid25Widget': (context) => GeneratedAndroid25Widget(),
'/GeneratedAndroid29Widget': (context) => GeneratedAndroid29Widget(),
'/GeneratedLowWidget12': (context) => GeneratedLowWidget12(),
'/GeneratedModerateWidget12': (context) => GeneratedModerateWidget12(),
'/GeneratedAndroid6Widget': (context) => GeneratedAndroid6Widget(),
'/GeneratedHoverStateWidget': (context) => GeneratedHoverStateWidget(),
'/GeneratedPlaceholderTextWidget7': (context) => GeneratedPlaceholderTextWidget7(),
'/GeneratedListBoxtitleWidget7': (context) => GeneratedListBoxtitleWidget7(),
'/GeneratedTextWidget': (context) => GeneratedTextWidget(),
'/GeneratedListboxComponentWidget7': (context) =>
GeneratedListboxComponentWidget7(),
'/GeneratedListboxComponentWidget8': (context) =>
GeneratedListboxComponentWidget8(),
'/GeneratedListboxComponentWidget9': (context) =>
GeneratedListboxComponentWidget9(),
'/GeneratedListboxComponentWidget10': (context) =>
GeneratedListboxComponentWidget10(),
'/GeneratedComponent1Widget1': (context) => GeneratedComponent1Widget1(),
'/GeneratedComponent3Widget1': (context) => GeneratedComponent3Widget1(),
'/GeneratedComponent8Widget': (context) => GeneratedComponent8Widget(),
'/GeneratedTextWidget1': (context) => GeneratedTextWidget1(),
'/GeneratedComponent2Widget': (context) => GeneratedComponent2Widget(),
'/GeneratedVectorWidget218': (context) => GeneratedVectorWidget218(),
'/GeneratedVectorWidget219': (context) => GeneratedVectorWidget219(),
'/GeneratedTextboxuncheckedWidget6': (context) =>
GeneratedTextboxuncheckedWidget6(),
'/GeneratedTextboxuncheckedWidget7': (context) =>
GeneratedTextboxuncheckedWidget7(),
'/GeneratedTextboxuncheckedWidget8': (context) =>
GeneratedTextboxuncheckedWidget8(),
'/GeneratedTextboxuncheckedWidget9': (context) =>
GeneratedTextboxuncheckedWidget9(),
'/GeneratedTextboxuncheckedWidget10': (context) =>
GeneratedTextboxuncheckedWidget10(),
'/GeneratedTextboxuncheckedWidget11': (context) =>
GeneratedTextboxuncheckedWidget11(),
'/GeneratedTextboxuncheckedWidget12': (context) =>
GeneratedTextboxuncheckedWidget12(),
'/GeneratedTextboxuncheckedWidget13': (context) =>
GeneratedTextboxuncheckedWidget13(),
'/GeneratedTextboxuncheckedWidget14': (context) =>
GeneratedTextboxuncheckedWidget14(),
'/GeneratedTextboxuncheckedWidget15': (context) =>
GeneratedTextboxuncheckedWidget15(),
'/GeneratedTextboxuncheckedWidget16': (context) =>
GeneratedTextboxuncheckedWidget16(),
'/GeneratedTextboxuncheckedWidget17': (context) =>
GeneratedTextboxuncheckedWidget17(),
'/GeneratedTextboxuncheckedWidget18': (context) =>
GeneratedTextboxuncheckedWidget18(),
'/GeneratedTextboxuncheckedWidget19': (context) =>
GeneratedTextboxuncheckedWidget19(),
'/GeneratedTextWidget2': (context) => GeneratedTextWidget2(),
'/GeneratedTextboxuncheckedWidget20': (context) =>
GeneratedTextboxuncheckedWidget20(),
'/GeneratedTextWidget3': (context) => GeneratedTextWidget3(),
'/GeneratedComponent4Widget1': (context) => GeneratedComponent4Widget1(),
'/GeneratedComponent7Widget1': (context) => GeneratedComponent7Widget1(),
'/GeneratedComponent5Widget1': (context) => GeneratedComponent5Widget1(),
'/GeneratedComponent6Widget3': (context) => GeneratedComponent6Widget3(),
'/GeneratedEllipse98Widget282': (context) => GeneratedEllipse98Widget282(),
'/GeneratedCheck_circleWidget': (context) => GeneratedCheck_circleWidget(),
'/GeneratedCheck_circleWidget1': (context) => GeneratedCheck_circleWidget1(),
'/GeneratedTEXTBARWidget15': (context) => GeneratedTEXTBARWidget15(),
'/GeneratedTEXTBARWidget16': (context) => GeneratedTEXTBARWidget16(),
'/GeneratedTEXTBARWidget17': (context) => GeneratedTEXTBARWidget17(),
'/GeneratedTEXTBARWidget18': (context) => GeneratedTEXTBARWidget18(),
'/GeneratedTEXTBARWidget19': (context) => GeneratedTEXTBARWidget19(),
'/GeneratedTEXTBARWidget20': (context) => GeneratedTEXTBARWidget20(),
'/GeneratedTEXTBARWidget21': (context) => GeneratedTEXTBARWidget21(),
'/GeneratedTEXTBARWidget22': (context) => GeneratedTEXTBARWidget22(),
'/GeneratedTEXTBARWidget23': (context) => GeneratedTEXTBARWidget23(),
'/GeneratedTEXTBARWidget24': (context) => GeneratedTEXTBARWidget24(),
'/GeneratedTEXTBARWidget25': (context) => GeneratedTEXTBARWidget25(),
},
);
}
}
Try removing this line from your code-
onGenerateRoute:generateRoute,
Also add this route in your routes section -
/GeneratedAndroid1Widget.
It should work fine then.

Flutter Bloc State won't be yielded after change from the Page pushed on top

The AddWorkoutEvent is dispatched correctly from the PageCreateWorkout with a DbMWorkout.
This will be inserted in the correct table of the DB.
The PageCreateWorkout will be notified with the WorkoutAddedState to go to PageWorkoutDetail with the given workoutId. The routes are stacked on the PageSelectWorkout, in which the WorkoutBloc is mainly used, to show all workouts. In there the PageSelectWorkout shall be refreshed with the new WorkoutLoadedState with the newly given workoutList. (The WorkoutList contains the added Workout, which I checked in the logger; but the State won't be yielded. Note that I am extending equatable to WorkoutStates.)
else if (event is AddWorkoutEvent) {
logger.i("AddWorkoutEvent | workout: ${event.workout}");
yield WorkoutLoadingState();
try {
DbMWorkout workout = await RepositoryWorkout.repo.add(event.workout);
yield WorkoutAddedState(id: workout.id);
List<DbMWorkout> workoutList = await RepositoryWorkout.repo.getAll();
logger.i("AddWorkoutEvent | workoutListLength: ${workoutList.length}");
yield WorkoutLoadedState(workoutList: workoutList); // <-- this state
} catch (e) {
yield WorkoutErrorState(message: e.toString());
}
}
The PageSelectWorkout is the initialPage of a Navigator in an indexedStack:
IndexedStack(
sizing: StackFit.expand,
index: _currentIndex,
children: <Widget>[
Navigator(
key: _pageOverview,
initialRoute: PageOverview.routeName,
onGenerateRoute: (route) =>
RouteGenerator.generateRoute(route)),
Navigator(
key: _pageSelectWorkoutNew,
initialRoute: PageSelectWorkout.routeName,
onGenerateRoute: (route) =>
RouteGenerator.generateRoute(route)),
Navigator(
key: _pageLog,
initialRoute: PageLog.routeName,
onGenerateRoute: (route) =>
RouteGenerator.generateRoute(route)),
Navigator(
key: _pageSettings,
initialRoute: PageSettings.routeName,
onGenerateRoute: (route) =>
RouteGenerator.generateRoute(route))
]),
The named Route to the SelectWorkout is wrapped with the correct Bloc in a BlocProvider:
case PageSelectWorkout.routeName:
return CupertinoPageRoute(
settings: settings,
builder: (context) {
return BlocProvider(
create: (context) => WorkoutBloc(),
child: PageSelectWorkout());
});
Note: In other Events like DeleteWorkoutEvent , which is happening without navigating to another Page, the updated State gets yielded correctly.
I found the answer after checking out some GitHub Issues and it's rather simple:
Since I want to access the same Bloc on 2 different Pages I can not just wrap a new Instance of the Bloc to each of the Page.
Instead I should wrap the BlocProvider with the WorkoutBloc higher in the WidgetTree Hierarchy for example in the main.dart
Before:
case PageSelectWorkout.routeName:
return CupertinoPageRoute(
settings: settings,
builder: (context) => BlocProvider(
create: (context) => WorkoutBloc(), // <-- Instance of WorkoutBloc
child: PageSelectWorkout()));
case PageCreateWorkout.routeName:
return CupertinoPageRoute(
settings: settings,
builder: (context) => BlocProvider(
create: (context) => WorkoutBloc(), // <-- Instance of WorkoutBloc
child: PageCreateWorkout(
workoutIndex: arguments["workoutIndex"],
workoutPosition: arguments["workoutPosition"],
),
));
After:
case PageSelectWorkout.routeName:
return CupertinoPageRoute(
settings: settings, builder: (context) => PageSelectWorkout());
case PageCreateWorkout.routeName:
return CupertinoPageRoute(
settings: settings,
builder: (context) => PageCreateWorkout(
workoutIndex: arguments["workoutIndex"],
workoutPosition: arguments["workoutPosition"],
),
);
and higher in the Inheritance/WidgetTree Hierarchy e.g. main.dart :
return MaterialApp(
debugShowCheckedModeBanner: false,
title: Strings.appTitle,
theme: AppTheme.darkTheme,
home: MultiBlocProvider(providers: [
BlocProvider<WorkoutBloc>(
create: (context) => WorkoutBloc(), // <-- put the Instance higher
),
BlocProvider<NavigationBloc>(
create: (context) => NavigationBloc(),
),
], child: BottomNavigationController()));

Flutter Web-Proper way to use both of onGenerateRoute and routes as properties of MaterialApp

I have a browser link of reset password that sent by email(http://trialxx.id/#/auth?email=trial#email.com ), so whenever user click that link I would like to navigate them to ResetPasswordScreen. So far I have been declaring the route inside onGenerateRoute, here is the code
Route<dynamic> generateRoute(RouteSettings settings) {
final settingsUri = Uri.parse(settings.name);
final postID = settingsUri.queryParameters['email'];
const start = "#/";
const end = "?";
final startIndex = settings.name.indexOf(start);
final endIndex = settings.name.indexOf(end, startIndex + start.length);
if (settings.name.substring(startIndex + start.length, endIndex) ==
"auth" &&
postID != null &&
postID != "") {
return MaterialPageRoute(
builder: (context) => RisetPasswordScreen(email: settings.name),
settings: RouteSettings(
name: '/${settings.name.substring(startIndex + start.length)}'));
}
else {
return MaterialPageRoute(builder: (context) => FirstScreen());
}
}
but, I didn't able to define it inside routes property, here is the way I define the route
MaterialApp(
debugShowCheckedModeBanner: false,
onGenerateRoute: generateRoute,
title: 'e-Recruitment',
initialRoute: '/',
routes: {
if (Uri.base.queryParameters['email'] != null &&
Uri.base.queryParameters['email'] != "")
if (Uri.base.toString().substring(
Uri.base.toString().indexOf("#/") + 2,
Uri.base
.toString()
.indexOf("?", Uri.base.toString().indexOf("#/") + 2)) ==
"auth")
'/auth': (context) => RisetPasswordScreen()
else
'/home': (context) => FirstScreen(),
'/': (context) => AnotherPage(),
'/second': (context) => SecondPage(),
})
so am I doing wrong or is there a proper way to define the routes of /auth?email=trial#email.com inside routes property?
You should keep routes simple. You want to define one route name per screen without any wildcards (as you try in your example).
In your material define only routes without parameters:
Widget test(){
return MaterialApp(
debugShowCheckedModeBanner: false,
onGenerateRoute: generateRoute,
title: 'e-Recruitment',
initialRoute: '/',
routes: {
'/auth': (context) => RisetPasswordScreen(),
'/home': (context) => FirstScreen(),
'/': (context) => AnotherPage(),
'/second': (context) => SecondPage(),
});
}
Then in your generateRoute() function parse uri just like you did, but without complicating things too much - parameter name in RouteSettings contains only path after /#. So if your link is http://trialxx.id/#/auth?email=trial#email.com, then settings.name will be /auth?email=trial#email.com
Route<dynamic> generateRoute(RouteSettings settings) {
var uri = Uri.parse(settings.name);
switch (uri.path) {
case home:
return MaterialPageRoute(builder: (_) => MyHomePage());
break;
case auth:
return MaterialPageRoute(
builder: (_) =>
ResetPasswordPage(email: uri.queryParameters["email"]));
break;
default:
return MaterialPageRoute(builder: (_) => ErrorPage());
}
}
Pass email as variable to the page and handle its logic there

SreamProvider containing specific documents

I have a streamProvider that contains all of the documents from a collection.
I want a StreamProvider that contains only certain documents. Can I use .where('agency', isEqualTo: 'some name'? Can this be done and if so how do I do it? Below is my current code:
'''
// From the main.dart
return MultiProvider(
providers: [
StreamProvider(create: (context) => firestoreService.getTrxns()),
],
child: MaterialApp(
initialRoute: WelcomeScreen.id,
routes: {
WelcomeScreen.id: (context) => WelcomeScreen(),
Home_Screen.id: (context) => Home_Screen(),
},
/// This is from a Services.dart file
Stream<List<Trxns>> getTrxns() {
return _db.collection('trxns').snapshots().map((snapshot) => snapshot.docs
.map((document) => Trxns.fromFirestore(document.data()))
.toList());
}
'''
That's exactly how you would do it:
_db.collection('trxns').where('agency', isEqualTo:
'some name').snapshots().map()

Initialize a dart class from a variable

Let's consider we have a list of pages and based on some logic, we want to display the corresponding route using Navigator. How do we do that?
final List<dynamic> components = [ PageA, PageB ]
..
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => new components[0]()),
);
There is routes attribute within material app widget. You should use that:
MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Sample',
home: Wrapper(),
routes: {
CarsList.routeName: (ctx) => PageOne(),
CarDisplay.routeName: (ctx) => PageTwo(),
OrdersScreen.routeName: (ctx) => PageThree(),
EditCar.routeName: (ctx) => PageFour(),
},
),
Before using that make sure that you have a static variable named as routeName in every widget.
static const routeName = '/PageOne';
I'm not entirely sure I understand you issuer but if your question is where/how you can put a condition there are two ways of doing so:
Let's say that based on condition you when to navigate to either components[0]() or components[1]() :
First:
final List<dynamic> components = [ PageA, PageB ]
..
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => condition ? new components[0]() : new component[1]()
),
);
Second:
final List<dynamic> components = [ PageA, PageB ]
..
Navigator.push(
context,
MaterialPageRoute(
builder: (context) {
if (condition) {
return new components[0]()
} else {
return new component[1]()
}
),
);