Flutter获取数据触发NoSuchMethodError:方法'[]'被调用在null上
问题排查:Flutter中NoSuchMethodError异常(调用null的[]方法)
异常详情
======== Exception caught by widgets library ======================================================= The following NoSuchMethodError was thrown building ProfileScreen(dirty, state: _ProfileScreenState#189a3): The method '[]' was called on null. Receiver: null Tried calling: []("firstname")
相关代码
class EditProfile extends Stateful Widget { const EditProfile({Key? key}) : super(key: key); @override _EditProfileState createState() => _EditProfileState(); } class _EditProfileState extends State<EditProfile> { bool isApiCallProcess = false; bool hidePassword = true; var _loadedProducts; late SharedPreferences _sharedPreferences; static final GlobalKey<FormState> globalFormKey = GlobalKey<FormState>(); final TextEditingController _firstnameController = TextEditingController(); final TextEditingController _lastnameController = TextEditingController(); final TextEditingController _emailController = TextEditingController(); final TextEditingController _mobileController = TextEditingController(); final TextEditingController _addressController = TextEditingController(); final validator1 = ValidationBuilder().email().maxLength(50).build(); String? firtname; String? lastname; String? email; String? mobile; String? address; @override void initState() { super.initState(); _fetchData(); } Future<void> _fetchData() async { var _sharedPreferences = await SharedPreferences.getInstance(); var userid = _sharedPreferences.getInt('userid'); if (userid != null) { userid = userid; } else { userid = 1; } print(userid.toString() + 'hello'); final response = await http.post( Uri.parse('${Utils.baseUrl}/profile/getData'), headers: {"Accept": "Application/json"}, body: {'user_id': userid.toString()}); if (response.statusCode == 200) { var decodedData = jsonDecode(response.body); print(decodedData); } else{ throw Exception('Failed to load..'); } var f_data = json.decode(response.body); print(f_data); setState(() { _loadedProducts = f_data["data"][0]; }); } }
问题原因及修复方案
核心原因
异常本质是UI渲染时_loadedProducts为null,直接调用_loadedProducts["firstname"]触发报错。具体诱因:
_fetchData是异步方法,UI会优先完成初始化渲染,此时_loadedProducts未被赋值,处于null状态- 接口返回的
f_data["data"]可能不存在、不是数组,或者数组为空,导致f_data["data"][0]返回null - 接口请求异常时直接抛出错误,未更新
_loadedProducts状态,导致其一直为null
修复步骤
1. 初始化_loadedProducts为默认值
避免初始状态为null,改为空Map:
var _loadedProducts = {};
2. 渲染前判断数据状态,显示加载提示
在build方法中先检查数据是否就绪,未就绪时显示加载状态:
@override Widget build(BuildContext context) { if (_loadedProducts.isEmpty) { return const Center(child: CircularProgressIndicator()); } // 原有UI渲染逻辑 return ...; }
3. 安全处理接口返回数据
确保data字段存在且有效后再赋值:
setState(() { // 多层判断避免空指针 if (f_data.containsKey("data") && f_data["data"] is List && f_data["data"].length > 0) { _loadedProducts = f_data["data"][0]; } else { _loadedProducts = {}; ScaffoldMessenger.of(context).showSnackBar( const SnackBar(content: Text("暂无用户数据")) ); } });
4. 取值时添加空安全防护
即使做了前置判断,取值时仍建议用空安全运算符:
// 替代直接_loadedProducts["firstname"] _loadedProducts?["firstname"] ?? ""
5. 完善异常捕获与状态更新
在异步请求中包裹try-catch,确保异常场景下_loadedProducts能被正确更新:
Future<void> _fetchData() async { try { var _sharedPreferences = await SharedPreferences.getInstance(); // 简化空判断逻辑 var userid = _sharedPreferences.getInt('userid') ?? 1; final response = await http.post( Uri.parse('${Utils.baseUrl}/profile/getData'), headers: {"Accept": "Application/json"}, body: {'user_id': userid.toString()}); if (response.statusCode == 200) { var f_data = json.decode(response.body); setState(() { if (f_data.containsKey("data") && f_data["data"] is List && f_data["data"].length > 0) { _loadedProducts = f_data["data"][0]; } else { _loadedProducts = {}; } }); } else { setState(() => _loadedProducts = {}); ScaffoldMessenger.of(context).showSnackBar( SnackBar(content: Text("加载失败:${response.statusCode}")) ); } } catch (e) { setState(() => _loadedProducts = {}); ScaffoldMessenger.of(context).showSnackBar( SnackBar(content: Text("请求异常:$e")) ); } }
内容的提问来源于stack exchange,提问作者Charudatt Palvi
相关产品推荐
相关产品推荐

