Контекст змінної члена можна отримати під час, initState
але не можна використовувати для всього. Це з метушні для initState
документації:
Ви не можете використовувати [BuildContext.inheritFromWidgetOfExactType]
цей метод. Однак, [didChangeDependencies]
буде викликаний відразу після цього методу, і [BuildContext.inheritFromWidgetOfExactType]
може бути використаний там.
Ви можете перенести свою логіку ініціалізації didChangeDependencies
, однак, можливо, це не саме те, що ви хочете, оскільки це didChangeDependencies
може бути викликано кілька разів у життєвому циклі віджета.
Якщо ви замість цього зробите асинхронний виклик, який делегує ваш дзвінок до того часу, поки віджет не буде ініціалізований, ви можете використовувати контекст, як ви задумали.
Простий спосіб зробити це - використовувати майбутнє.
Future.delayed(Duration.zero,() {
... showDialog(context, ....)
}
Інший спосіб, який може бути більш "правильним", полягає у використанні планувальника флаттера для додавання зворотного виклику після кадру:
SchedulerBinding.instance.addPostFrameCallback((_) {
... showDialog(context, ....)
});
І нарешті, ось маленький трюк, який я люблю робити, щоб використовувати асинхронні виклики у функції initState:
() async {
await Future.delayed(Duration.zero);
... showDialog(context, ...)
}();
Ось повністю розроблений приклад із використанням простого 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,
),
],
),
),
);
}
}
Маючи більше контексту з ОП, що міститься у коментарях, я можу дати трохи краще рішення їх конкретної проблеми. Залежно від програми, ви можете прийняти рішення, виходячи з того, яку сторінку показувати, залежно від того, чи відкривається програма вперше, тобто встановлено home
щось інше. І діалоги не обов’язково є найкращим елементом інтерфейсу на мобільному; може бути краще показати повну сторінку з налаштуваннями, які їм потрібно додати, і наступну кнопку.
MaterialApp
«shome
власність. Тому я насправді не роблю там поштовху. Не могли б ви дати мені приклад, як це зробити уbuild
функції? В даний час він просто повертає новийScaffold
зappBar
,drawer
,body
іfloatingActionButton