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

Flutter实现ListView.builder时Note.fromJson报预期String得Null错误如何解决

问题原因
  • JSON字段映射错误:你调用的https://jsonplaceholder.typicode.com/posts接口返回的单条数据内容字段为body,而非text,所以json['text']取到Null,赋值给非空String类型的text属性触发类型不匹配报错。
  • 网络请求逻辑不规范:你将请求方法放在build函数中,每次组件重绘都会重复发起请求,且请求完成后更新数组没有调用setState,不会触发界面刷新。
修复方案

步骤1:修正Note类的字段映射

给字段取值添加默认空兜底,同时匹配接口实际返回的字段:

class Note {
  late String title;
  late String text;

  Note(this.title, this.text);
  Note.fromJson(Map<String, dynamic> json) {
    // 匹配接口返回的body字段,取不到时给默认值避免空异常
    title = json['title'] ?? '无标题';
    text = json['body'] ?? '无内容';
  }
}

如果你需要兼容字段可能为空的场景,也可以将属性声明为可空类型,使用时判空即可:

class Note {
  String? title;
  String? text;

  Note(this.title, this.text);
  Note.fromJson(Map<String, dynamic> json) {
    title = json['title'];
    text = json['body'];
  }
}
// 界面使用时添加判空逻辑
Text(_notes[index].title ?? '无标题')
Text(_notes[index].text ?? '无内容')

步骤2:修正网络请求调用逻辑

将请求放到initState中仅执行一次,请求完成后调用setState更新界面:

class _MyAppState extends State<MyApp> {
  List<Note> _notes = [];
  // 添加加载状态用于展示加载动画
  bool _isLoading = true;

  @override
  void initState() {
    super.initState();
    // 页面初始化时发起请求
    fetchNotes();
  }

  Future<void> fetchNotes() async {
    var response = await http.get(Uri.parse("https://jsonplaceholder.typicode.com/posts"));
    var notes = <Note>[];
    if (response.statusCode == 200) {
      var notesJson = jsonDecode(response.body);
      for (var noteJson in notesJson) {
        notes.add(Note.fromJson(noteJson));
      }
    }
    // 更新状态触发重绘
    setState(() {
      _notes = notes;
      _isLoading = false;
    });
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
        home: Scaffold(
            appBar: AppBar(
              title: Text("Listview with Json"),
            ),
            body: _isLoading 
                ? const Center(child: CircularProgressIndicator())
                : ListView.builder(
              itemBuilder: (context, index) {
                return Card(
                  child: Padding(
                    padding: const EdgeInsets.only(
                        top: 32.0, bottom: 32.0, left: 16.0, right: 16.0),
                    child: Column(
                      crossAxisAlignment: CrossAxisAlignment.start,
                      children: <Widget>[
                        Text(
                          _notes[index].title,
                          style: TextStyle(
                              fontSize: 22, fontWeight: FontWeight.bold),
                        ),
                        Text(
                          _notes[index].text,
                          style: TextStyle(color: Colors.grey.shade700),
                        )
                      ],
                    ),
                  ),
                );
              },
              itemCount: _notes.length,
            )));
  }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.06 03:21:02