How to move a variable outside build? - flutter

How do I move a variable that uses a context outside of the build method so that it is created once?
class _EventListState extends State<EventList> {
#override
Widget build(BuildContext context) {
final eventNotifier = EventInherited.of(context).eventNotifier;
...

You can use the late modifier.
class _EventListState extends State<EventList> {
late final eventNotifier = EventInherited.of(context).eventNotifier;
#override
Widget build(BuildContext context) {
...

make
eventNotifier
class variable and connect it to the getter function.
class _EventListState extends State<EventList> {
var? eventNotifier;
#override
Widget build(BuildContext context) {
eventNotifier = EventInherited.of(context).eventNotifier;
}
Dynamic get getEventNotifier => this.eventNotifier;

You can use the didChangeDependencies() method. The context is available at that point.
#override
void didChangeDependencies(){
super.didChangeDependencies();
final eventNotifier = EventInherited.of(context).eventNotifier;
}
This method will be called again in certain scenarios, so be careful about what you are initializing.
This thread has more information on when it is recalled, but in general it is okay to use for initialing listeners.
Understanding Flutter didChangeDependencies mechanics

Related

How can I use initState in a widget build to reference the value of riverpod?

I want to assign the value of currentUser.profilepictureURL to ListImage.
But if I put the initState outside of the widget build, it will be out of scope. Please tell me.
class _MyHomePageState extends ConsumerState<MyHomePage> {
var listImage = [];
#override
Widget build(BuildContext context) {
final currentUser = ref.watch(userModelProvider);
void initState() {
listImage.add(currentUser.profilePictureURL);
super.initState();
}
return Container();
}
}
The way your are using initState is wrong. InitState is an #override and it should not to be used inside a build method.
try this:
class _MyHomePageState extends ConsumerState<MyHomePage> {
var listImage = [];
#override
Widget build(BuildContext context) {
final currentUser = ref.watch(userModelProvider);
listImage.add(currentUser.profilePictureURL);
return Container();
}
}

How to use stateful widget parameters in state class at construction without adding the widget to the tree?

I stumped into a problem where I need to use a StatefulWidget parameter in its state class when it's constructed, but I couldn't find a way to do it since using widget.[whatever variable name] in the state's class constructor returns an unexpected null value, and the initState function only runs when the widget is being drawn to the screen.
For example:
import 'package:flutter/material.dart';
class Test extends StatefulWidget {
final String text;
Test(this.text);
final state = _TestState();
#override
_TestState createState() => state;
}
class _TestState extends State<Test> {
String? changingText;
void updateChangingText(String moreText){
changingText = changingText! + moreText;
}
#override
void initState() {
super.initState();
changingText = widget.text;
}
#override
Widget build(BuildContext context) {
return Text(changingText!);
}
}
class App extends StatelessWidget {
#override
Widget build(BuildContext context) {
var w = Test('test');
w.state.updateChangingText(' text');
return MaterialApp(home: Scaffold(body:
Test('test text')
));
}
}
void main() {
runApp(App());
}
This doesn't work since changingText is being updated before initState gives it its initial value since it only runs when Text is being drawn to the screen and this:
import 'package:flutter/material.dart';
class Test extends StatefulWidget {
final String text;
Test(this.text);
final state = _TestState();
#override
_TestState createState() => state;
}
class _TestState extends State<Test> {
String? changingText;
void updateChangingText(String moreText){
changingText = changingText! + moreText;
}
_TestState(){
changingText = widget.text;
}
#override
Widget build(BuildContext context) {
return Text(changingText!);
}
}
class App extends StatelessWidget {
#override
Widget build(BuildContext context) {
var w = Test('test');
w.state.updateChangingText(' text');
return MaterialApp(home: Scaffold(body:
Test('test text')
));
}
}
void main() {
runApp(App());
}
doesn't work either since you can't use widget.[whatever] in state class constructors (for some reason).
So what can I do to use widget parameters in the state class before the widget is drawn to the screen?
Thanks in advance for the help
You should use the initState method present in the State for this instead of the constructor
#override
void initState() {
changingText = widget.text;
super.initState();
}

How to use ever() with Flutter getx variable in GetxController if I didn't add .obs

I am using Flutter getx package.
I know how to use "ever" with (.obs) variable like this
class CountController extends GetxController {
final count = 0.obs;
#override
void onInit() {
ever(count1, (_) => print("$_ has been changed"));
super.onInit();
}
}
But how to use "ever()" or triggering specific callbacks when variable change if the variable doesn't have (.obs) because I am using GetBuilder (not : Obx or GetX) in my view
class AnyScreen extends StatelessWidget {
final controller = Get.put(CounterController());
#override
Widget build(BuildContext context) {
ever(controller.counter, (value) => print("$value has been changed"));
}
#override
Widget build(BuildContext context) {
return Text("whatever!");
}
}
NOTE: Workers should always be used when starting a Controller or Class, so it should always be on onInit (recommended), Class constructor, or the initState of a StatefulWidget (this practice is not recommended in most cases, but it shouldn't have any side effects)
docs

How do I access an variable from a StatefulWidget inside an StatelessWidget?

How do I access the variable "selectedTag" from this statefulWidget:
class _AlertDialogOneState extends State<AlertDialogOne> {
Item selectedTag;
...
}
}
inside this statelessWidget :
class CardTile extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Container(...
Pass it as parameter,
class CardTile extends StatelessWidget {
final Item selectedTag;// Add this
CardTile(this.selectedTag); // Add this
#override
Widget build(BuildContext context) {
return Container(...
To pass this variable, you have multiple ways:
Pass it as a constructor when u navigate to this class using your navigator
Navigator.push(
context,
MaterialPageRoute(builder: (context) => CardTile(selectedTag)),
);
class CardTile extends StatelessWidget {
Item selectedTag;
CardTile(this.selectedTag);
#override
Widget build(BuildContext context) {
return Container(...
Use a state management like provider
class ProviderData with ChangeNotifier {
Item selected;
void changeSelection(newSelect) {
selected = newSelect;
changeNotifier();
}
}
and inside any class you need call this:
final providerData = Provider.of<ProviderData>(context);
so you can access the variable or change it using this instance like this:
final variable = providerData.selected;
providerData.changeSelection(newValue);
print(variable);
hope this help but i see that it is better to pass it through the constructor if you are not using a state managemnt, however i just gave you an example for illustration

Reason for changing Flutter stateful widget's final widget variable while state variable doesn't

Consider the following code snippet:
class CustomStateFulWidget extends StatefulWidget {
final GlobalKey<NavigatorState> navigatorKeyFinal = GlobalKey();
#override
_CustomStateFulWidget createState() => _CustomStateFulWidget();
}
class _CustomStateFulWidget extends State<CustomStateFulWidget> {
GlobalKey<NavigatorState> navigatorKeyLocal = GlobalKey();
#override
Widget build(BuildContext context) {
print("Navigator key local: ${navigatorKeyLocal.hashCode}");
print("Navigator key final: ${widget.navigatorKeyFinal.hashCode}");
return Center();
}
}
In the above code for every time the build method of _CustomStateFulWidget called, the navigatorKeyFinal variable value changes, but the navigatorKeyLocal variable stay unchanged. Can anyone explain me the reason of this behaviour?