home of materialApp in dart language - flutter

my question is about the structure of the widgets.
this line of code:
return new MaterialApp(
title: "question",
home: MyApp(),
);
if there is a navigator on MyApp() class to navigat to another Screen (LoginScreen()), the MyApp() class will be as its parent or will be destried and the other Screen (LoginScreen()) will be as
this line of code:
return new MaterialApp(
title: "question",
home: LoginScreen(),
);

The MaterialApp already provides a Navigator. You should only have one MaterialApp in your app and all your screens should be children of the one app.
MyApp -> MaterialApp
-> HomeScreen
-> LoginScreen
You can follow this basic example on flutter.io: https://flutter.dev/docs/cookbook/navigation/navigation-basics
Also you don't need the new keyword anymore. Any IDE (VSCode/IntelliJ) should give you a hint there if it is correctly configured.

Related

How can I implement navigation routes in flutter

I have design my scenario to understanding about the flow.
Dashboard Screen=> open side Drawer =>Select any menu=> First screen=> second screen=>open dialog(second screen)=> First screen=> Side drawer.
I want to use above like this navigation flow, when I click inside the dialog button I want to go First screen than first screen to click back button so go to side drawer.
I'm using the below code for navigate screen.
Navigator.of(context).pushNamed(screenName);
Please suggest me to how I can implement my above mention flow.
you can give each screen a route name like this :
class MyApp extends StatelessWidget {
const MyApp({super.key});
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
routes: {
"/home_page" : (context) => MyHomePage(),
"/keep_alive": (context) => const KeepAliveExample()
},
initialRoute: "/home_page",
);
}
}
like this you will set all of your routes , and set an initial route that the application will run at the start.
when you want to navigate to another screen you will do this :
Navigator.of(context).pushNamed(screenName);
and the screen name will be the route that you give it in the material app.
you can change the pushNamed to others styles navigations like :
Navigator.of(context).pushNamedAndRemoveUntil(newRouteName, (route) => false);
Navigator.of(context).pushReplacementNamed(routeName);
Navigator.of(context).popAndPushNamed(routeName);

How can i add 2 functions in void main before run app , in Flutter?

I need to run 2 function inside my main.dart file, before run app.
One is the bottom navigation bar, the other one is the easy localization.
My main.dart is:
void main() => runApp(
MyApp()
);
Future <void> main() async {
WidgetsFlutterBinding.ensureInitialized();
await EasyLocalization.ensureInitialized();
runApp(
EasyLocalization(
supportedLocales: [Locale('en', 'US'), Locale('it', 'IT'), Locale('fr', 'FR')],
path: 'assets/translations', // <-- change the path of the translation files
fallbackLocale: Locale('en', 'US'),
assetLoader: CodegenLoader(),
child: MyLangApp(),
),
);
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context){
return new MaterialApp(
home: MyBottomNavBar(),
);
}
}
So basically, i cannot have 2 void main inside the main.dart. How can i put the 2 functions together?
There are two separate parts to your question, and the answers are different.
You're making main() async, and that handles your localization. If you want even more control, we had a discussion about using async functions before rendering the first frame on HumpDayQandA this week, and went into how you can extend the native splash screen as long as needed so your functions can finish. It's the episode for 29 June, 2022 on the FlutterCommunity YouTube channel. https://www.youtube.com/watch?v=9KFk4lypFD4
The BottomAppBar issue is probably why you got dinged for a -1 on this question. That's because this isn't how you use BottomAppBar. It goes in a Scaffold. If you want to not have the AppBar on top then just leave it out.
But you don't want to be calling a BottomNavBar as the home parameter of a MaterialApp. Whatever you use for home is going to be the foundational visible widget in your tree, the lowest widget that all others are built on.
Does your whole app fit inside that BottomNavBar? Then you want to put the bar inside of something else that takes up the whole screen and provides a base to build the rest of your app on... Like a Scaffold.

Flutter initial routes with parameters

I need to pass an argument for my initialRoute. I found this issue and tried it like this:
initialRoute: AuthService.isLoggedIn() ? Views.home : Views.firstStart,
onGenerateInitialRoutes: (String initialRouteName) {
return [
AppRouter.generateRoute(
RouteSettings(
name: AuthService.isLoggedIn() ? Views.home : Views.firstStart,
arguments: notificationPayloadThatLaunchedApp,
),
),
];
},
onGenerateRoute: AppRouter.generateRoute,
This almost works. The problem I have is that somehow after calling this...
Navigator.pushReplacementNamed(
context,
Views.loading,
);
... my Multiprovider which is a parent of my GetMaterialApp is being called again which crashed my app because I call a function when initializing my providers:
#override
Widget build(BuildContext context) {
return MultiProvider(
providers: [
ChangeNotifierProvider(
create: (context) {
var dataProvider = DataProvider();
dataProvider.init( // <- this is called again which should not happen
context,
);
return dataProvider;
},
),
],
child: GetMaterialApp(
title: 'Flutter Boilerplate',
navigatorKey: Get.key,
initialRoute: AuthService.isLoggedIn() ? Views.home : Views.firstStart,
onGenerateInitialRoutes: (String initialRouteName) {
return [
AppRouter.generateRoute(
RouteSettings(
name: AuthService.isLoggedIn() ? Views.home : Views.firstStart,
arguments: notificationPayloadThatLaunchedApp,
),
),
];
},
onGenerateRoute: AppRouter.generateRoute,
),
);
}
I feel like the way how I pass the initial argument is wrong. Is there any other/better way to get this done? Let me know if you need any more info!
I think you misunderstand the usage of new API onGenerateInitialRoutes cause by the name it should load without the calling of
Navigator.pushReplacementNamed(
context,
Views.loading,
);
API at all. if you call this route from another widget, it means this is already the second route already. it should be the default route for your application. so it makes no sense to give a parameter to an initial route at all.
since you have used Provider Package, it is better to just get whatever argument(parameter) that you want to send via Provider API itself.
if you want to give hardcoded data, then just treat it as a normal Widget class.
home: MyHomePage(name:"parameter name",data:DataHome()), :
GetMaterialApp(
title: 'Flutter Boilerplate',
navigatorKey: Get.key,
home: MyHomePage(name:"parameter name",data:DataHome()),
onGenerateRoute: AppRouter.generateRoute,
);
take note that if you calling Navigator.pushReplacementNamed API . your provider will be gone cause of the Flutter Widget Tree most Navigator API will create a new Widget tree level from the root. since the provider only provides for all its child only. so you cant use any provider data since you have a different ancestor.
so if you only have one page to go I suggest you use the home attribute in MaterialApp API cause it will treat your initial page as a child and Provider API can receive the data cause up in the Widget tree, it has an Ancestor Provider API:
MultiProvider(
providers: [
ChangeNotifierProvider(
if you want to move between pages via navigator after the main page.
consider using NestedNavigator so flutter will not create a new route from the root of the widget tree. so you still can access Provider API's data.
guessing from your variable name. I assume that you want to handle a notification
routing, check this deeplink

Where to place a Provider Widget -- Flutter Provider Package

I am currently learning app development with Flutter and have started learning about the Provider package. I was having some difficulty and was getting the error:
"Could not find the correct Provider above this ... Widget"
I ended up moving the Provider widget to wrap around my MaterialApp widget instead of my Scaffold Widget, and that seemed to fix things.
That being said, I'm not sure why this fixed things. Are we supposed to put our Provider widget around our MaterialApp? If so, can someone please explain why this is needed? If not, can someone explain how to determine where to place the Provider widget in our tree?
Usually, the best place is where you moved it, in the MaterialApp. This is because since that is where the app starts, the node tree will have access to the provider everywhere.
If your page is a Stateful widget - inside Widget wrap State with Provider, so you can use it inside of State. This is a much cleaner solution because you won't have to wrap your entire application.
If you need the functionality of Provider everywhere in the app - yes, wrapping the entire app is completely fine, though I'll prefer to use some kind of service for this
You could add it to any route and pass it to the route you need to use or you can add it to MaterialApp
so you can use it anywhere.
The best practice of using provider:
Place the Provider widget at the top of the widget tree. Bellow I put a template code that can be used for one more providers at the same place, by using MultiProvider widget under Provider package.
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MultiProvider(
providers: [
ProviderName<ModelName>(create: (_) => ModelName()),
AnotherProviderName<AnotherModelName>(create: (_) => AnotherModelName()),
],
child: MaterialApp(
title: 'App title',
theme: ThemeData(
primarySwatch: Colors.blue,
primaryColor: const Color(0xFF2196f3),
accentColor: const Color(0xFF2196f3),
canvasColor: const Color(0xFFfafafa),
),
home: MyHomePage(), // Your widget starting
),
);
}
}
For more informatin: https://pub.dev/documentation/provider/latest/

Problem in displaying localized labels in Dart

I am not able to set localization in my app.
I am trying to add language settings and associated localization in my app. I am able to get-set the language option. I am using 'intl' plug-in for internationalization. My code looks like below in pretty much all the UI .dart files.
AppTranslations.of(context).accountNumber +
" ${accountDetails.accountNumber}",
The getters is set as :
String get accountNumber => _text("account_number");
String _text(String key) {
return _localisedValues[key] ?? _defaultLocaleValues[key];
}
I've also placed json files containing localized labels in 3 different languages. However, it seems there is some instantiation problem of the locazation plug-in. The code doesn't go the getter line.
Any help would be highly appreciated.
AppTranslations.of(context) is a standard way of accessing the localised labels. You are right about the instantiation. If the program doesn't go to the getter line them it means, there's a problem in somewhere in the initial part of the code. It could be in the main.dart.
Check where you are initialising LocalStorageProvider(). In case it is not initialised then that's the problem. Assuming you are using a MaterialApp, try the below suggestion then :
Wrap the MaterialApp with LocalStorageProvider(). I mean, in the main widget build, return LocalStorageProvider() and pass your existing code of MaterialApp() as a child to it. Sample below (Please ignore the theme etc since I just copied the code from one of my app) :
#override
Widget build(BuildContext context) {
LocalStorage localStorage = LocalStorage();
return LocalStorageProvider(
localStorage: localStorage,
child: LocaleProvider(
localStorage: localStorage,
localeWrapper: LocaleWrapper(),
child: Builder(
builder: (context) {
return AnimatedBuilder(
animation: LocaleProvider.of(context).localeWrapper,
builder: (context, _) {
return MaterialApp(
onGenerateTitle: (context) =>
AppTranslations.of(context).appName,
locale: LocaleProvider.of(context).locale,
title: "App Title",
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MapsDemo(),
localizationsDelegates: [
AppTranslationsDelegate(
LocaleProvider.of(context).supportedLanguagesCodes,
),
GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
],
supportedLocales: LocaleProvider.of(context).supportedLocales,
);
},
);
},
),
),
);
}