flutter - 创建 StatefulWidget 时访问 Flutter 上下文
问题描述
初始化有状态小部件时,我无法访问服务对象。问题来自该context
对象在initState
.
我InheritedWidget
用来在我的文件中注入一个服务对象,main.dart
就像这样
void main() async {
final sqflite.Database database = await _openDatabase('db.sqlite3');
runApp(
Services(
database: database,
child: MyApp(),
),
);
}
Services
对象非常简单。它将不仅仅是database
一个成员。这个想法是小部件不需要知道是否正在访问本地数据库、本地缓存或远程服务器。
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
对象。我无法访问其中的Services
对象,initState
所以我正在使用didChangeDependencies
. 从堆栈中删除主页时会出现问题。它似乎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;
});
}
}
解决方案
对于这种情况,您可以在构建小部件后使用addPostFrameCallback
您的WidgetsBinding
实例执行一些代码。
_onLayoutDone(_) {
this._loadAnimals();
}
@override
void initState() {
WidgetsBinding.instance.addPostFrameCallback(_onLayoutDone);
super.initState();
}
推荐阅读
- python - 对于列表:NoneType 对象没有附加属性
- javascript - 从 useSelector react-redux 钩子获取未定义
- javascript - 循环遍历对象数组以更新对象值并附加其他对象
- angular - 如何在茉莉花中模拟新的承诺块
- docker - 使用 docker 安装 mongodb
- java - 如何让加载活动等到线程完成
- python-3.x - 如何删除数据框中的重复值,同时保留 Pandas 中的其余行?
- netlogo - 如何将使用“values-from”语法的代码重写为使用“of”语法的代码
- android - 如何确定Android视图百分比可见区域何时发生变化?
- netbeans - 将 derby.jar 数据库添加到 jdk 1.8.0_191