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

Flutter中App启动时解析加载JSON文件的异步问题及解决

问题分析与解决方案

问题所在

readJson()是异步方法(返回Future<void>),你调用它时没有使用await关键字,导致代码不会等待异步操作完成就直接执行后续的print(myNotes.notes)。这时候JSON文件还没加载、解码完成,_notes还是初始的空Map,所以打印结果为空。

你的理解误区

你误以为调用异步方法会同步等待它执行完毕,但Dart的异步机制是:调用异步方法后会立即返回一个Future对象,代码继续向下执行;只有通过await或者监听Future的完成状态,才能确保在异步操作结束后再处理结果。另外,build()方法本身是同步执行的,不能直接在build()里使用await(因为build()不能被标记为async)。

代码修正方案

方案1:使用StatefulWidget的initState初始化加载

适合需要在页面初始化时加载数据,并手动管理加载状态的场景:

import 'package:flutter/services.dart' show rootBundle;
import 'dart:convert';

class Notes {
  Map _notes = {};
  Map get notes => _notes;

  Future<void> readJson() async {
    final String response = await rootBundle.loadString('assets/sample.json');
    final data = json.decode(response); // json.decode本身不是异步方法,无需await
    _notes = data;
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({super.key});

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  late Notes myNotes;
  bool _isLoading = true;

  @override
  void initState() {
    super.initState();
    myNotes = Notes();
    _loadNotes();
  }

  Future<void> _loadNotes() async {
    await myNotes.readJson();
    // 更新状态触发重建,此时数据已加载完成
    setState(() {
      _isLoading = false;
    });
    print(myNotes.notes); // 这里能输出正确的JSON内容
  }

  @override
  Widget build(BuildContext context) {
    if (_isLoading) {
      return const Scaffold(
        body: Center(child: CircularProgressIndicator()),
      );
    }

    return Scaffold(
      body: Center(
        child: Text(myNotes.notes.toString()),
      ),
    );
  }
}

方案2:使用FutureBuilder处理异步状态

更简洁的方式,无需手动管理加载状态,适合直接依赖异步数据渲染UI的场景:

import 'package:flutter/services.dart' show rootBundle;
import 'dart:convert';

class Notes {
  Map _notes = {};
  Map get notes => _notes;

  Future<void> readJson() async {
    final String response = await rootBundle.loadString('assets/sample.json');
    final data = json.decode(response);
    _notes = data;
  }
}

class MyHomePage extends StatelessWidget {
  const MyHomePage({super.key});

  Future<Notes> _loadNotes() async {
    final notes = Notes();
    await notes.readJson();
    return notes;
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: FutureBuilder<Notes>(
        future: _loadNotes(),
        builder: (context, snapshot) {
          if (snapshot.connectionState == ConnectionState.waiting) {
            return const Center(child: CircularProgressIndicator());
          } else if (snapshot.hasError) {
            return Center(child: Text('加载失败:${snapshot.error}'));
          } else {
            final myNotes = snapshot.data!;
            print(myNotes.notes); // 这里能输出正确的JSON内容
            return Center(
              child: Text(myNotes.notes.toString()),
            );
          }
        },
      ),
    );
  }
}

后续扩展说明

如果后续要加载非本地文件(比如网络接口),只需修改readJson()方法的实现,替换成网络请求逻辑即可,外部的状态管理和UI渲染逻辑无需大幅改动,保持异步方法的封装性即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.29 08:40:30