Flutter使用MobX时ListView.builder热重载前页面空白无数据问题
问题根因
你遇到的问题是MobX异步action的常见陷阱:
- 你给
initReporting方法加了@action注解,但async函数中await关键字之后的代码是异步执行的,已经脱离了原@action的执行上下文,后续对entries数组的修改没有被MobX捕获,因此不会触发响应式更新。热重载会强制触发页面重建,直接读取已经修改完成的entries数据,所以才能正常显示内容。 - 你采用逐个
add元素修改observable数组的方式,也存在一定概率无法触发MobX的数组变更监听。
修复方案
1. 修正Provider层异步数据修改逻辑
将await之后的状态修改逻辑用runInAction包裹,同时直接替换整个数组代替逐个添加元素,保证MobX能监听到变更:
@action Future initReporting(context) async { try { isLoading = true; Response _readings = await sl<IIndividualDataService>().getAllRmssd(); Map<String, dynamic> map = _readings.data; List<dynamic> data = map["readings"]; // 异步逻辑放入runInAction runInAction(() { if (data != null) { entries = data.map((v) => IndvidualReadings.fromJson(v)).toList(); } isLoading = false; }); } catch (err) { runInAction(() { isLoading = false; }); print(err.toString()); } }
2. 优化页面层代码(可选,优化依赖追踪)
提前获取Provider实例存为局部变量,避免每次build重复调用服务定位器获取实例,同时可以补充加载状态提升体验:
class IndividualDataState extends State<IndividualData> { final IIndividualDataProvider provider = sl<IIndividualDataProvider>(); @override void initState() { super.initState(); setup(); provider?.initReporting(context); } @override Widget build(BuildContext context) { return Observer( builder: (_) => Scaffold( backgroundColor: Colors.grey[100], appBar: AppBar( elevation: 0, centerTitle: true, title: Text("All Data"), backgroundColor: PRIMARY, ), body: Stack( children: <Widget>[ if (provider.isLoading) const Center(child: CircularProgressIndicator()), ListView.builder( itemCount: provider.entries.length, itemBuilder: (BuildContext context, int index) { final item = provider.entries[index]; return ListTile( title: Text(item.entry.toString()), subtitle: Text(item.createdAt.toString()), ); }, ), ], ), ), ); } }
额外检查项
确认你本地已经正确执行了MobX代码生成命令flutter pub run build_runner build,确保生成的关联代码没有异常。
内容的提问来源于stack exchange,提问作者Vivian Lobo
相关产品推荐
相关产品推荐

