I'm not sure if the initState
is the right function for this.
What I'm trying to achieve is to check when the page is rendered to perform some checks and based on them opening a AlertDialog
to make some settings if needed.
I've got a Page which has a state.
It's initState
function looks like this:
@override
void initState() {
super.initState();
if (!_checkConfiguration()) {
_showConfiguration(context);
}
}
The _showConfiguration
like this:
void _showConfiguration(BuildContext context) {
AlertDialog dialog = new AlertDialog(
content: new Column(
children: <Widget>[
new Text('@todo')
],
),
actions: <Widget>[
new FlatButton(onPressed: (){
Navigator.pop(context);
}, child: new Text('OK')),
],
);
showDialog(context: context, child: dialog);
}
If there's a better way to make this checks and if needed call the modal, please point me in the proper direction, I was looking for a onState
or onRender
function, or a callback I could assign to the build
function to be called on render but wasn't able to find one.
Edit: It seams over here they had a similar problem: Flutter Redirect to a page on initState
If you instead make an asynchronous call which delegates your call until after the widget has been initialized, you can then use context as you intend. A simple way to do that is to use a future. With more context from the OP provided in comments, I can give a slightly better solution to their specific problem.
InitState() is used to subscribe to the object. Overriding of initState() method performs initialization which depends on the location at which this object was inserted into the tree (like context) or on the widget used to configure this object (or widget).
The member variable context can be accessed during initState
but can't be used for everything. This is from the flutter for initState
documentation:
You cannot use
[BuildContext.inheritFromWidgetOfExactType]
from this method. However,[didChangeDependencies]
will be called immediately following this method, and[BuildContext.inheritFromWidgetOfExactType]
can be used there.
You could move your initialization logic to didChangeDependencies
, however that might not be exactly what you want as didChangeDependencies
can be called multiple times in the lifecycle of the widget.
If you instead make an asynchronous call which delegates your call until after the widget has been initialized, you can then use context as you intend.
A simple way to do that is to use a future.
Future.delayed(Duration.zero,() {
... showDialog(context, ....)
}
Another way, which may be more 'correct', is to use flutter's scheduler to add a post-frame callback:
SchedulerBinding.instance.addPostFrameCallback((_) {
... showDialog(context, ....)
});
And finally, here's a little trick I like to do to use asynchronous calls in the initState function:
() async {
await Future.delayed(Duration.zero);
... showDialog(context, ...)
}();
Here's a fully fleshed out example using the simple Future.delayed:
import 'dart:async';
import 'package:flutter/material.dart';
void main() => runApp(new MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
int _counter = 0;
bool _checkConfiguration() => true;
void initState() {
super.initState();
if (_checkConfiguration()) {
Future.delayed(Duration.zero,() {
showDialog(context: context, builder: (context) => AlertDialog(
content: Column(
children: <Widget>[
Text('@todo')
],
),
actions: <Widget>[
FlatButton(onPressed: (){
Navigator.pop(context);
}, child: Text('OK')),
],
));
});
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'You have pushed the button this many times:',
),
Text(
'$_counter',
style: Theme.of(context).textTheme.display1,
),
],
),
),
);
}
}
With more context from the OP provided in comments, I can give a slightly better solution to their specific problem. Depending on the app, you may actually want to make a decision based on which page to show depending on whether it's the first time the app is opened i.e. set home
to something different. And dialogs aren't necessarily the best UI element on mobile; it may be better to show a full page with the settings they need to add and a next button.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With