You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter加载本地JSON文件返回null报错求助

解决Flutter中FutureBuilder调用[]方法时的null错误

嗨,刚看了你的代码,这个问题很典型——FutureBuilder的builder回调会被多次触发,第一次触发时异步请求还没完成,snapshot.data是null,这时候你直接调用json.decode(snapshot.data.toString()),相当于解码字符串"null",结果mydata还是null,后续访问mydata[index]自然就会抛出"The method '[]' was called on null."的错误。

问题根源拆解

当使用FutureBuilder时,它会经历几个关键状态:

  • 初始加载状态:snapshot.connectionState为ConnectionState.waiting,此时snapshot.data为null
  • 请求完成状态:snapshot.connectionState变为ConnectionState.done,请求成功时snapshot.data才有有效数据
  • 请求错误状态:如果加载失败,snapshot.hasError会变为true

你当前的代码没有处理这些状态,直接跳过加载过程去解析数据,自然会遇到null的问题。

修复方案

我们需要在builder里先判断snapshot的状态,分情况处理:

  1. 请求加载中时,显示加载指示器
  2. 请求出错时,显示错误提示
  3. 请求成功且有数据时,再安全解析JSON并构建列表

下面是修改后的完整代码,关键修改处我用注释标出来了:

import 'package:flutter/material.dart';
import 'dart:convert';

void main() {
  runApp(MaterialApp(
    home: Home(),
    theme: ThemeData(
      primarySwatch: Colors.indigo,
    ),
  ));
}

class Home extends StatefulWidget {
  @override
  HomeState createState() => HomeState();
}

class HomeState extends State<Home> {
  List data;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text("Some App"),
      ),
      body: Container(
        child: Center(
          child: FutureBuilder(
            future: DefaultAssetBundle.of(context).loadString('assets/data.json'),
            builder: (context, snapshot) {
              // 1. 处理加载中状态
              if (snapshot.connectionState == ConnectionState.waiting) {
                return const CircularProgressIndicator();
              }

              // 2. 处理错误状态
              if (snapshot.hasError) {
                return Text('加载出错:${snapshot.error}');
              }

              // 3. 确保数据不为null后再解析
              if (snapshot.data == null) {
                return const Text('没有数据');
              }

              // 现在可以安全解析JSON了
              var mydata = json.decode(snapshot.data.toString());
              print(mydata);

              return ListView.builder(
                itemBuilder: (BuildContext context, int index) {
                  return Card(
                    child: Column(
                      crossAxisAlignment: CrossAxisAlignment.stretch,
                      children: <Widget>[
                        Text("Name " + mydata[index]['Name']),
                        // 注意:如果Age是数字类型,要转成字符串再拼接
                        Text("Age " + mydata[index]['Age'].toString()),
                        Text("Gender " + mydata[index]['Gender']),
                      ],
                    ),
                  );
                },
                itemCount: mydata.length,
              );
            },
          ),
        ),
      ),
    );
  }
}

额外小提示

  • 如果你的data.json里的Age字段是数字类型,一定要转成字符串再和"Age "拼接,否则会触发类型错误(我已经在代码里加了注释提醒)
  • 用const修饰不需要变化的Widget(比如静态文本、加载指示器),能小幅提升页面性能
  • 可以把Future请求移到initState方法中执行,避免每次页面build都重复发起请求(对于本地JSON文件影响不大,但养成好习惯很重要)

内容的提问来源于stack exchange,提问作者Sachihiro

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.13 07:42:29