在 Widget 的 initState 或初始化生命周期中使用 Provider
Using Provider in Widget's initState or initialising life-cycle
所以在学习Flutter的过程中,似乎initState()
不是使用Providers的地方,因为它还没有访问必须通过的context
。我的讲师解决这个问题的方法是将 didChangeDependencies()
生命周期挂钩与标志结合使用,这样内部的任何代码都不会 运行 多次:
bool _isInit = true;
@override
void didChangeDependencies() {
if (_isInit) {
// Some provider code that gets/sets some state
}
_isInit = false;
super.didChangeDependencies();
}
这对我来说是一种糟糕的开发体验。在可以访问 context
的 Flutter Widget 中,是否没有其他方法 运行ning 初始化代码?或者有没有计划引入一些更可行的东西?
我见过的唯一其他方法是使用 Future.delayed
,感觉有点“hacky”:
@override
void initState() {
Future.delayed(Duration.zero).then(() {
// Some provider code that gets/sets some state
});
super.initState();
}
我在didChangeDependencies里面实现如下
@override
void didChangeDependencies() {
super.didChangeDependencies();
if (_isInit) {
setState(() {
_isLoading = true;
});
Provider.of<Products>(context).fetchAndSetProducts().then((_) {
setState(() {
_isLoading = false;
});
});
}
_isInit = false;
}
可以将代码安排到 运行 当前帧的末尾。如果安排在 initState()
内,似乎在代码为 运行ning 时 Widget 已完全设置。
为此,您可以使用 SchedulerBinding
实例的 addPostFrameCallback 方法:
@override
void initState() {
super.initState();
SchedulerBinding.instance.addPostFrameCallback((_) {
// Some provider code that gets/sets some state
})
}
您也可以为此使用 WidgetsBinding.instance.addPostFrameCallback()
。在 Widget built/loaded 之后,出于 运行ning 代码的目的,它们的行为相同,但是 here 是关于差异的更多细节。
注意:一定要导入SchedulerBinding需要的文件:
import 'package:flutter/scheduler.dart';
您可以将 Provider 放在一个单独的函数中,然后在 initState()
中调用该函数
bool isInit = true;
Future<void> fetch() async {
await Provider.of<someProvider>(context, listen: false).fetch();
}
@override
void initState() {
if (isInit) {
isInit = false;
fetch();
}
isInit = false;
super.initState();
}
所以在学习Flutter的过程中,似乎initState()
不是使用Providers的地方,因为它还没有访问必须通过的context
。我的讲师解决这个问题的方法是将 didChangeDependencies()
生命周期挂钩与标志结合使用,这样内部的任何代码都不会 运行 多次:
bool _isInit = true;
@override
void didChangeDependencies() {
if (_isInit) {
// Some provider code that gets/sets some state
}
_isInit = false;
super.didChangeDependencies();
}
这对我来说是一种糟糕的开发体验。在可以访问 context
的 Flutter Widget 中,是否没有其他方法 运行ning 初始化代码?或者有没有计划引入一些更可行的东西?
我见过的唯一其他方法是使用 Future.delayed
,感觉有点“hacky”:
@override
void initState() {
Future.delayed(Duration.zero).then(() {
// Some provider code that gets/sets some state
});
super.initState();
}
我在didChangeDependencies里面实现如下
@override
void didChangeDependencies() {
super.didChangeDependencies();
if (_isInit) {
setState(() {
_isLoading = true;
});
Provider.of<Products>(context).fetchAndSetProducts().then((_) {
setState(() {
_isLoading = false;
});
});
}
_isInit = false;
}
可以将代码安排到 运行 当前帧的末尾。如果安排在 initState()
内,似乎在代码为 运行ning 时 Widget 已完全设置。
为此,您可以使用 SchedulerBinding
实例的 addPostFrameCallback 方法:
@override
void initState() {
super.initState();
SchedulerBinding.instance.addPostFrameCallback((_) {
// Some provider code that gets/sets some state
})
}
您也可以为此使用 WidgetsBinding.instance.addPostFrameCallback()
。在 Widget built/loaded 之后,出于 运行ning 代码的目的,它们的行为相同,但是 here 是关于差异的更多细节。
注意:一定要导入SchedulerBinding需要的文件:
import 'package:flutter/scheduler.dart';
您可以将 Provider 放在一个单独的函数中,然后在 initState()
bool isInit = true;
Future<void> fetch() async {
await Provider.of<someProvider>(context, listen: false).fetch();
}
@override
void initState() {
if (isInit) {
isInit = false;
fetch();
}
isInit = false;
super.initState();
}