在初始化有状态小部件时,我在访问服务对象时遇到问题。问题来自于 context
对象在 initState
中不可用。
我正在使用 InheritedWidget
在我的 main.dart
文件中注入(inject)服务对象,如下所示
void main() async {
final sqflite.Database database = await _openDatabase('db.sqlite3');
runApp(
Services(
database: database,
child: MyApp(),
),
);
}
Services
对象非常简单。它不仅仅是数据库
作为成员。这个想法是,小部件不需要知道是否正在访问本地数据库、本地缓存或远程服务器。
class Services extends InheritedWidget {
final Database database;
const Services({
Key key,
@required Widget child,
@required this.database,
}) : assert(child != null),
assert(database != null),
super(key: key, child: child);
Future<List<models.Animal>> readAnimals() async {
return db.readAnimals(database: this.database);
}
@override
bool updateShouldNotify(InheritedWidget oldWidget) {
return false;
}
static Services of(BuildContext context) {
return context.inheritFromWidgetOfExactType(Services) as Services;
}
}
当我想从数据库加载所有动物时,问题出现在我的 _HomePageState
状态中。我需要访问 Services
对象。我无法访问 initState
中的 Services
对象,因此我使用 didChangeDependency
。当主页从堆栈中删除时就会出现问题。看起来 didChangeDependences
被调用并且对上下文对象的访问是非法的。因此,我创建了一个 _initialized
标志,可以在 didChangeDependencies
中使用它,以确保我只在第一次加载动物。 这看起来很不优雅。有更好的办法吗?
class _HomePageState extends State<HomePage> {
bool _initialized = false;
bool _loading = false;
List<Animal> _animals;
@override
Widget build(final BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(Strings.of(this.context).appName),
),
body: _HomeBody(
loading: this._loading,
animals: this._animals,
),
);
}
@override
void didChangeDependencies() {
super.didChangeDependencies();
if (!this._initialized) {
this._initialized = true;
this._loadAnimals();
}
}
void _loadAnimals() async {
this.setState(() {
this._loading = true;
this._animals = null;
});
final List<Animal> animals = await Services.of(this.context).readAnimals();
this.setState(() {
this._loading = false;
this._animals = animals;
});
}
}
最佳答案
对于这种情况,您可以使用 WidgetsBinding
实例的 addPostFrameCallback
在构建小部件后执行一些代码。
_onLayoutDone(_) {
this._loadAnimals();
}
@override
void initState() {
WidgetsBinding.instance.addPostFrameCallback(_onLayoutDone);
super.initState();
}
关于flutter - 创建 StatefulWidget 时访问 Flutter 上下文,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56729848/