Flutter中在DropdownButton使用JSON列表遇空指针红屏问题求助
问题解决思路
核心问题分析
- jsonList作用域错误:你在
readJson方法里定义的jsonList是局部变量,无法被customJsonDropDown方法访问,导致DropdownButton尝试调用null.map()触发空指针。 - 未初始化成员变量:即使把
jsonList改为类成员,若未初始化为空列表,在JSON加载完成前它会是null,可能引发潜在错误。 - Dropdown初始值不匹配:如果初始
value和jsonList中的选项不匹配,也会导致Dropdown报错。
修正步骤
1. 定义类成员变量
在你的State类中声明jsonList并初始化为空列表:
List jsonList = [];
2. 修改readJson方法
把局部变量改为给成员变量赋值,同时移除json.decode前多余的await(它是同步方法):
Future<void> readJson() async { final response = await rootBundle.loadString('assets/json/units.json'); final data = json.decode(response); setState(() { jsonList = data["length"] as List; print(jsonList); }); }
3. 处理Dropdown初始值
在State类中添加选中值变量,并在JSON加载完成后初始化:
String? selectedValue; // 在readJson的setState中补充: selectedValue = jsonList.first['conversion'].toString();
4. 调整customJsonDropDown方法
添加加载状态判断,确保JSON未加载完成时显示占位符:
Widget customJsonDropDown(String? value, void Function(String?) onChange) { if (jsonList.isEmpty) { return Container( height: 50, decoration: BoxDecoration( borderRadius: BorderRadius.circular(9), color: Colors.white, ), child: const Center(child: Text("加载中...")), ); } return Container( decoration: BoxDecoration( borderRadius: BorderRadius.circular(9), color: Colors.white, ), child: Padding( padding: const EdgeInsets.only(left: 10, right: 5), child: SizedBox( height: 50, child: DropdownButton<String>( value: value, onChanged: onChange, items: jsonList.map((item) { return DropdownMenuItem( child: Text(item['name']), value: item['conversion'].toString(), ); }).toList(), underline: Container(), isExpanded: true, ), ), ), ); }
5. 初始化时加载JSON
在State的initState中调用readJson,确保页面启动时加载数据:
@override void initState() { super.initState(); readJson(); }
额外优化建议
创建数据模型类解析JSON,避免直接使用Map,提升代码可读性和类型安全性:
class Unit { final String name; final double conversion; final bool isBaseUnit; Unit({required this.name, required this.conversion, this.isBaseUnit = false}); factory Unit.fromJson(Map<String, dynamic> json) { return Unit( name: json['name'], conversion: json['conversion'], isBaseUnit: json['base_unit'] ?? false, ); } }
修改readJson的解析逻辑:
setState(() { jsonList = (data["length"] as List).map((item) => Unit.fromJson(item)).toList(); selectedValue = (jsonList.first as Unit).conversion.toString(); });
对应的DropdownMenuItem调整为:
items: (jsonList as List<Unit>).map((unit) { return DropdownMenuItem( child: Text(unit.name), value: unit.conversion.toString(), ); }).toList(),
内容的提问来源于stack exchange,提问作者Ahmad
相关产品推荐
相关产品推荐

