Flutter空安全下JSON解析时snapshot.data属性访问空报错如何解决
问题解决步骤
你遇到的报错本质上是空安全下AsyncSnapshot.data本身是可选类型,即便你判断了hasData,Dart也不会默认把它提升为非空类型,再加上你有两个隐藏代码问题会叠加报错:getData()方法没有返回解析后的模型实例、FutureBuilder没有完整处理加载/错误状态。按照以下步骤修改即可解决:
1. 修复getData()方法的返回逻辑
你原来的getData只做了JSON解码,没有转成模型实例也没有返回值,即便页面判断有数据,拿到的也是null,补全逻辑如下:
Future<AutoGenerate> getData() async { final response = await http.get(Uri.parse('MyURL')); // 先判断请求是否成功 if (response.statusCode == 200) { var data = json.decode(response.body); // 返回解析后的模型实例 return AutoGenerate.fromJson(data); } else { throw Exception('接口请求失败'); } }
2. 优化FutureBuilder的判断逻辑,安全访问属性
方案1:局部变量类型提升(全版本兼容,官方推荐)
在判断hasData之后把snapshot.data赋值给局部变量,Dart会自动把它提升为非空类型,不需要额外的空断言:
@override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(), body: Container( alignment: Alignment.center, child: SafeArea( child: SingleChildScrollView( child: FutureBuilder<AutoGenerate>( future: getData(), builder: (context, AsyncSnapshot<AutoGenerate> snapshot) { // 处理加载中状态 if (snapshot.connectionState == ConnectionState.waiting) { return const CircularProgressIndicator(); } // 处理请求错误状态 if (snapshot.hasError) { return Text('加载失败:${snapshot.error}'); } // 处理有数据的场景 if (snapshot.hasData) { // 赋值给局部变量,自动提升为非空类型 final autoData = snapshot.data!; return Container( child: Card( elevation: 1.2, color: Colors.yellowAccent[100], child: Padding( padding: EdgeInsets.all(16.0), child: Text('Sun Rise :${autoData.SunRise}'), ), ), ); } // 兜底空状态 return const Text('暂无数据'); }, ), ), ), ), ); }
方案2:模式匹配(Dart 3.0+ 更简洁)
如果你的项目使用Dart 3.0以上版本,可以用模式匹配直接处理所有状态,代码更精简:
builder: (context, AsyncSnapshot<AutoGenerate> snapshot) { return switch(snapshot) { AsyncSnapshot(loading: true) => const CircularProgressIndicator(), AsyncSnapshot(error: final e) => Text('加载失败:$e'), AsyncSnapshot(data: final autoData?) => Card( elevation: 1.2, color: Colors.yellowAccent[100], child: Padding( padding: EdgeInsets.all(16.0), child: Text('Sun Rise :${autoData.SunRise}'), ), ), _ => const Text('暂无数据') }; }
补充优化建议
- 模型类属性建议符合Dart小驼峰命名规范,你可以在
fromJson中手动做字段映射,或者用json_serializable注解自动生成序列化代码,避免手写序列化逻辑出错。 - 示例接口返回的
SunRise字段值是5.30:00,中间是点而非冒号,如果后续需要转成DateTime类型使用,要先做格式替换。
内容的提问来源于stack exchange,提问作者Purna Satya
相关产品推荐
相关产品推荐

