Call constructor every time i access in a page Flutter - flutter

I want to call a constructor from a class everytime i login in app, the first time it's all ok but the next times is no called.
Im using stateless widget and provider.
Elements:
a simple class whit a constructor
class FetchDataFromTheWeb extends ChangeNotifier{
FetchDataFromTheWeb(){
loadingData();
}
Future loadingData(){
// And more code
}
}
My stateless widget
class HomeScreen extends StatelessWidget {
const HomeScreen({Key? key}) : super(key: key);
final conferencesServices = Provider.of<FetchDataFromTheWeb>(context);
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Hello')),
body: ListWhitFetchedData()
);
}
}
Situation:
Im login in the app and the content is loaded by the method in constructor, but if im logout and login again whit a different account the constructor is not called and the data previously loaded is kept to the new user and they need to be load manually by the new user (and this is not the idea...).
Exist the way to recharge or recall the constructor when i want?
Thanks

Related

How to use GetxController inside my view without removing the const keyword on the constructor

using Getx, when I have a GetxController and I want to use it inside my view UI, it required removing const on the widget constructor :
Controller :
class TestController extends GetxController {
// ...
}
View :
class TextWidget extends StatelessWidget {
const TextWidget({super.key}); // throws error
final controller = Get.put(TestController());
#override
Widget build(BuildContext context) {
return Container();
}
}
it throws an error on the const line :
> Can't define the 'const' constructor because the field 'controller' is initialized with a non-constant value.
so it requires me to delete the const, but since adding const is recommended for better performance, I want to let it there and use my controller.
I could shut down this error by declaring the controller inside the build() method, but I guess it's not a good idea.
First of all, create a controller
class HomeController extends GetxController {}
Then create an instance of that controller inside the binding
class HomeBinding extends Bindings {
#override
void dependencies() {
Get.put<HomeController>(HomeController());
}
}
Then extends your view with GetView and Assign HomeController to generic type of GetView
class HomePage extends GetView<HomeController> {
const HomePage({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Homepage')),
);
}
}
while navigating to that page you can initialize that binding too which will create the instance of that controller
await Get.to(
() => const HomePage(),
binding: HomeBinding(),
);
you can access variables and functions residing inside HomeController by using controller. and controller. i.e. controller.connectButtonAction(), controller.userName
declaring controllers inside the build() method will cause to extra unnecessary Get.put() that will be called every time widget rebuilds.
Instead of calling your controller as a variable like this:
final controller = Get.put(TestController());
You prevent this error and let your widget const, by using a getter to get the GetxController like this:
TestController get controller => Get.put(TestController());
You can use the controller now simply like you will do if you declare it as final, and your widget is still const.
Consider also using GetView<T> since it makes you achieve the same thing:
class TextWidget extends GetView<TestController> {
const TextWidget({super.key});
#override
Widget build(BuildContext context) {
return Text("${controller.index}"); // use controller directly to access controller.
}
}
You need just to specify the generic type of your controller with GetView<T>, then you can refer to that controller with the controller getter without defining it manually.

How to access a variable data from the state of a flutter stateful widget from another stateful widget class's state

Hi guys I am facing a problem which I have tried to solve through multiple approaches but failed. I have a stateful widget class which has a variable in its state I need to access the data in this variable from another stateful widget's class's state, I have tried accessing the variable by creating a GlobalKey for the class which contains the variable, but when I access the variable I get null. Am I accessing the variable the wrong, way or is there a more appropriate way of doing it?
what i usually do in cases like this is i will define varableX globally so that i can access it from anywhere in my app. To do this install flutter_riverpod and define variableX like this:
final variableXProvider = StateProvider<bool>((ref)=> false/true);
inside your build method, you can access it like this
class StatefulWidget1 extends ConsumerStatefulWidget {
const StatefulWidget1({Key? key}) : super(key: key);
#override
ConsumerState<ConsumerStatefulWidget> createState() => _StatefulWidget1State();
}
class _StatefulWidget1State extends ConsumerState<StatefulWidget1> {
#override
Widget build(BuildContext context) {
//* watch variableX like this
final varibleX = ref.watch(variableXProvider.state).state;
return Scaffold(body: Column(
children: [
Text(varibleX),
//* to change the value of variableX you can do this
ElevatedButton(onPressed: (){
ref.read(variableXProvider.notifier).state = true/false;
}, child: Text('Change value'))
],),);
}
}
once you hit the button, the value changes without needing to call setState(). the ref object will automatically rebuild itself once it detects any changes.

Pass parameters to a route widget correctly

I am new to flutter, and have some difficulties understanding how to correctly pass parameters to a widget that is navigated to.
My goal is, that when the users clicks on a button, I want to start up a wizard controller with a certain enum parameter based on what button the user clicked.
The wizard controller has an app bar but the primary content is a dynamic child wizard flow widget which is chosen based on the enum parameter. The wizard controller (and its children) needs to be stateful because it, among other things, holds information about the current page in the chosen wizard flow and a model which holds data for the whole wizard flow.
As far as I can see there are two options of instantiating the wizard controller with the enum parameter:
Option 1.
//Pass the parameters when the route is pushed
onPressed: () {
Navigator.pushNamed(context, '/wizard', arguments: EFlowType.WizardFlow2);
},
//In the build method, extract the parameter from the navigator, and use it here:
class WizardController extends StatefulWidget {
WizardController({Key? key}) : super(key: key);
#override
State<WizardController> createState() => _WizardControllerState();
}
class _WizardControllerState extends State<WizardController> {
StatefulWidget? dynamicWidget;
#override
void initState() {
super.initState();
}
#override
Widget build(BuildContext context) {
final flowType = ModalRoute.of(context)!.settings.arguments as EFlowType;
switch (flowType) {
case EFlowType.WizardFlow1:
//Prepare models, set dynamicWidget and do alot of work
break;
case EFlowType.WizardFlow2:
//Prepare models, set dynamicWidget and do alot of work
break;
}
return Scaffold(
appBar: AppBar(
title: Text('Wizard controller'),
),
body: dynamicWidget
);
}
....
The problem is here that I would like to access the flowType parameter in the initState (or in the WizardController class constructor), so I dont need to do all the initialization work every time the widget is being rebuild/UI is updated.
If I try to access the flowtype in the initstate I get this error which I cannot come around: FlutterError (dependOnInheritedWidgetOfExactType<_ModalScopeStatus>() or dependOnInheritedElement() was called before _WizardControllerState.initState() completed.
It is not possible to access the context in the WizardController class, so that is not an option.
Option 2.
In the MaterialApp method I can declare an extra onGenerateRoute setting, for these routes in my app that has parameters:
class WizardController extends StatefulWidget {
EFlowType flowType = EFlowType.MeterChange;
WizardController({Key? key, required this.flowType}) : super(key: key);
#override
State<WizardController> createState() => _WizardControllerState();
}
onGenerateRoute: (RouteSettings settings) {
if (settings.name == '/wizard') {
return MaterialPageRoute(builder: (_) => WizardController(flowType: settings.arguments as EFlowType));
}
This makes the flowType available in the initState. But why on earth would I declare context and logic-specific stuff where I am defining my routes? Is this a preferred way of defining widget parameters?
So how would you normally go around this quite normal problem?

Flutter - Navigator.push() giving error "Context does not include a Navigator" on extends State<Main>

I've been creating a flutter app for a society and i'm using flutter.
I have created two "window" (I don't really know the technical terms on flutter),
The first one will display correctly with a button to switch on the second.
If you click on the button the other window will display correctly.
But, i want to use DeepLinks (for the notifications), and if i click on the link, the redirect in the _AccueilPageState to the Pub class (I'm using
Navigator.push(context,MaterialPageRoute(builder: (context) => Pub()));
I got the error
Navigator operation requested with a context that does not include a
Navigator
Someone can explain me what is wrong ? And maybe how to fix this issue !
Thanks,
Here you can see the hierachi of my code (I can't show all of it because of confidentiality):
void main() async{...}
class MyApp extends StatefulWidget {
const MyApp({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return this;
}
#override
State<StatefulWidget> createState() => _AccueilPageState();
}
//Loading properties for MyApp(with the navigator.push in it)
class _AccueilPageState extends State<MyApp>{...}
//class loading FenetrePrincipale
class WebView extends StatelessWidget{
#override
Widget build(BuildContext context) {
return MaterialApp(home : FenetrePrincipale(),
);
}
}
//Pub that return a MaterialApp(home:Builder:(context)=>Scaffold())
class Pub extends StatelessWidget{...}
//FenetrePrincipale that return a Scaffold
class FenetrePrincipale extends StatelessWidget{...}
//When on FenetrePrincipale we can push a button to open Pub but if you go trough a deeplink : _AccueilPageState
//Does not redirect on Pub and put the error :
//"Navigator operation requested with a context that does not include a Navigator"
Create a global key for the navigator so you can access it from anywhere in the application:
final GlobalKey<NavigatorState> myNavigatorKey = GlobalKey<NavigatorState>();
Assign it to your app when creating MaterialApp:
return MaterialApp(navigatorKey: myNavigatorKey,...);
Use it when pushing routes:
myNavigatorKey.currentState?.pushNamed(...);

Declare AppBar in another dart file and instantiate it with an different file

It's the 4th day of my Flutter. I used to use Unity.
Currently my project has 3 pages; Home, Profile, Settings
These pages are transitioned using Navigator.
The AppBar is declared in the Scaffold within each page, but the AppBar for all pages is the same.
So I have to write three of the same code. (always need to write and modify the same code as the number of pages increases in the future)
So I thought it looks good to declare AppBar as a variable and the page would just call it.
Like this:
//originappbar.dart
AppBar originAppBar(
backgroundColor: .....
)
//home.dart
class ShowHome extends StatelessWidget {
ShowHome({Key? key}) : super(key: key);
static const String route = '/home';
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: originAppBar(), ....
//profile.dart
//Same as home.dart
In the above example, I'm trying to assign the originAppBar created by originappbar.dart to appbar: in home.dart or profile.dart.
But I can't declare AppBar as a variable.
I'm confused because I thought I could make AppBar a variable.
What's wrong with my code?
Thank you.
PreferredSizeWidget originAppBar = new AppBar(
backgroundColor: .....
)
//home.dart
class ShowHome extends StatelessWidget {
ShowHome({Key? key}) : super(key: key);
static const String route = '/home';
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: originAppBar, ....
//profile.dart
//Same as home.dart
You can create a stateless widget like:
class CustomAppBar extends StatelessWidget implements PreferredSizeWidget{
///Here goes your duplicated code
}
And just use that CustomAppBar everywhere.
Or create a widget CustomScaffold that is nothing more than the scaffold that you use in all your pages but with the CustomAppbar and any other hanges made.