Flutter首次启动加载JSON文件时dataJsonObject返回null热重载后正常
问题原因
你遇到的现象本质是异步执行时序导致的:
你在initState中调用的getJsonProverb是异步函数,Dart执行异步函数时不会等待它执行完成,会直接继续走后续的生命周期流程,首次触发build方法时,JSON文件还没完成加载、解析,所以dataJsonObject还是初始的null值。
而热重载/热重启不会清空内存中已经缓存的变量,此时dataJsonObject已经在上次运行时完成赋值,所以能正常显示。
解决方案
Flutter官方针对异步资源渲染的标准方案是使用FutureBuilder组件,你可以按以下代码修改:
import 'package:flutter/material.dart'; import 'dart:convert'; import 'package:flutter/services.dart'; import 'package:flutter/foundation.dart'; class ProverbDisplay extends StatefulWidget { final int myId; final String myCountry; const ProverbDisplay(this.myId, this.myCountry); @override _ProverbDisplayState createState() => _ProverbDisplayState(); } class _ProverbDisplayState extends State<ProverbDisplay> { // 获取JSON方法,明确返回值类型 Future<Map<String, dynamic>> getJsonProverb() async { final String rawJson = await rootBundle.loadString('assets/json/data.json'); // jsonDecode是同步方法,不需要加await Map<String, dynamic> dataJsonObject = jsonDecode(rawJson); return dataJsonObject; } @override void initState() { super.initState(); // 不需要在这里调用异步方法 } @override Widget build(BuildContext context) { return FutureBuilder<Map<String, dynamic>>( future: getJsonProverb(), builder: (context, snapshot) { // 加载中状态,展示加载指示器 if (snapshot.connectionState == ConnectionState.waiting) { return const Center(child: CircularProgressIndicator(color: Colors.white,)); } // 加载出错状态,展示错误提示 if (snapshot.hasError) { return Center(child: Text('加载失败:${snapshot.error}')); } // 加载完成,取数据正常渲染 Map<String, dynamic> dataJsonObject = snapshot.data!; debugPrint(' jsonData : $dataJsonObject'); return Container( color: Colors.blue, height: 250, child: Row( children: [ Container( width: 300, child: PageView.builder(itemBuilder: (context, index) { return Text("$dataJsonObject"); }), ), ], ), ); }, ); } }
核心修改说明
- 用
FutureBuilder包裹原有渲染逻辑,它会自动监听异步方法的执行状态,等异步执行完成后再触发渲染,不会出现首次运行拿空值的问题 - 新增了加载中、加载出错的兜底状态,既避免空指针异常,也提升了用户体验
- 移除了
initState中的异步调用,也不需要再用全局变量存储JSON解析结果,直接从snapshot.data中取即可
内容的提问来源于stack exchange,提问作者user5824983
相关产品推荐
相关产品推荐

