Like every other app that I created I have some boilerplate code that I need to execute before loading the application:
session check
store hydration
route change listener
user session listener
...
This code, more often than not, requires a BuildContext context to be available. I cannot use the context that sits at the same level with MaterialApp due to complaints from flutter so I need to go deeper 1+ levels in order to grab a context from a descendant. That descendant is my home route and it obviously fails when you navigate away.
What is a proper place to grab a context and initiate my watchers app wide? Where would you continuously watch for a navigation change for example?
Related
I am new to bloc and I found that whenever I am creating a new page with it's own bloc, I have to create a Loading state and ShowLoading event repeatedly. What is the best practice to avoid this? I have tried multiple ways such as BaseBloc and BaseState, which allows others bloc to inherit it but none of them work. Is there any implementation or boiler plate for this? Thank you.
when you wat to use BaseBloc you will end up with writing with a code that is not nicely written and you can not use it in the root of the widget tree.
the Bloc way from what I notice is that each bloc is related to a Page/feature and each one will have it's own loading state and that Page will respond to it's loading state, you can notice that in the documentation page under Naming Conventions
to run around that issue usually I would go to make my loading widget inside a snack bar with loader inside it, and call it each time there is a loading state. that will make it easy to change it in the future from one place or maybe you can search for some library that can do the loading for you each time you call some method from the blocs.
another idea is to wrap the root widget with a provider that will trigger a loading widget on the root top of the widget each time you call some provider method(like showLoader() ), and from inside the bloc/blocs you can call the provider method that will trigger the loading each time from anywhere, maybe this resource is helpful for that .
I was trying to change url using Navigator 2.0
As far as I can understand, Routing System call RouteInformationParser.restoreRouteInformation to update url when RouterDelegate's notifyListener method called
My problem is to rebuild all Widget when RouterDelegate's notifyListener called
For example, I have changed part of the screen and would like to apply related information to the URL. At this time, there is no need to rebuild the screen.
If you change the current configuration value of RouterDelegate and call the notifyListener function, it rebuild the screen and change the URL.
Is there a way to change the URL only?
Iam using EventChannel to handle events from hardware barcode scanner. EventChannel is initialized in initState, in main class - it works through whole app. While change is detected, it inserts value into global variable (ValueNotifier - i dont know, if it is right) and then I need to work with that value in multiple widgets. I need some sort of widget, which will tell me, that value updated and it will trigger onEvent function - something like RawKeyboardListener. I tried using listeners, but when i do pushNamed, the listener is still listening and it runs code from previous pages, while scanning.
Is there any widget, that would be suitable for me? (cant use ValueListenableBuilder, because it has no "onEvent" function) Or is there any way, to remove and add listeners while moving between pages, or while modal bottom sheet is opened? (I need to access previous listeners, after Navigator.pop)
I solved my problem by using listeners and ModalRoute.of(context).isCurrent.
in Flutter,
I am calling provider functions to load data from database in main.dart and I saw that main.dart is calling them continuously, so I added bool to check if they called or if they are loading now to stop continuous calls, after that it started to concern me. Is this way okay? What is the better way? I don't want to add it to the first pages initstate as if user has details in SharedPreferences, I wait and send token to get different data.
Here is the calling part in main.dart file.
Checks if user has details in SharedPreferences.
Loads chats if user has details in SharedPreferences.
Connects to socket if not connected before.
If user has details, starts loading and in the first step it makes isLoadingUserForMain = false so that until it loads and gets responds it won't be able to call.
Please tell me your opinion thanks..
Look the best way of doing what you want to achieve is...
Make an Splash or middle screen of loading.
push all the asynchronous task at that Widget.
You can handle anything there.
It is not recommended to do asynchronous tasks in main function. So you need to make Material app to do the tasks..
I would have a splash screen like #Akash mentions, but I would call these methods when your provider is initialized. For example, lets say you create your providers like this at the top of your app:
runApp(MultiProvider(providers: [
Provider<DatabaseService>(
create: (_) => YourService(),
lazy: false,
),
],
child: MyApp()));
Your init logic in the question would exist in the constructor of YourService.
Now you could have a stream of userDetails that your splash screen will listen to and once it emits details go to the appropriate screen.
My flutter app is showing a splash screen (statefulWidget) as a first route. This route is showing an animation while, on the background, calling an API to get some data.
Once the data has been received and the animation is complete, it navigates to the second route.
All works fine, except that, when calling the Navigator to navigate to the second route, the second route is shown, but i can see again the response from the API on the first route, that is being called.
It turns out that, when the second route is built, the build method of the previous route is called too, making an unnecessary API call again.
How to avoid this behaviour?, I believe this must be a bug on Flutter??
current flow (non-desired): SplashRoute(build) ---> Navigator ---> HomeRoute(build)+SplashRoute(build)
desired flow: SplashRoute(build) ---> Navigator ---> HomeRoute(build)
What you are trying to do is to work against the framework. It's a futile effort. Instead, you should work with the framework. Here is why and how:
Build methods should not make API requests. Build methods should use fields of your state class to generate a UI without any side effects.
Please move your API calls to the initState method, save their results in fields of your state class with setState and get the build method to use them without generating any side effects.