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

Flutter从Hive取数据首次运行列表为空 热重启后才显示问题

问题根因
  • 代码存在明显变量名笔误:getData()方法中await Hive.openBox('venuesBox')得到的盒子实例名为venueBox,但setState里读取数据时用的是未在该方法内定义的venuesBox,存在实例引用不一致的竞态问题。首次进入页面时读取的是未完成初始化的盒子实例,拿到空数据;热重启后全局盒子实例完成初始化,才能读到数据。这也是直接读本地json的readJson()方法能正常运行的核心原因之一——该方法不存在变量引用错误。
  • 未在应用启动入口完成Hive前置初始化:如果在main函数中没有等待Hive初始化、盒子打开、自定义类适配器注册完成就直接runApp,会出现Hive操作时序问题,首次运行时异步开盒的速度慢于首帧渲染速度,导致空列表。
  • 未处理首次运行时Hive盒子无数据的场景:测试时热重启能读到数据,是因为之前调试流程中已经把数据写入过Hive持久化存储,但首次冷启动安装应用时,刚创建的Hive盒子本身是空的,自然读不到数据。
修复步骤
  1. 先修正应用入口main函数的Hive初始化逻辑,确保所有Hive相关前置操作在runApp之前完成,从根源避免时序竞态:
void main() async {
  // 绑定Flutter插件引擎,否则异步调用原生插件能力会报错
  WidgetsFlutterBinding.ensureInitialized();
  // 初始化Hive本地存储
  await Hive.initFlutter();
  // 如果Venue是自定义类,提前注册Hive TypeAdapter,否则无法正确解析存储的对象
  // Hive.registerAdapter(VenueAdapter());
  // 提前打开业务需要用到的盒子,不用在每个页面里重复openBox
  await Hive.openBox('venuesBox');
  runApp(const MyApp());
}
  1. 修正getData()方法的变量笔误,同时补充首次运行空盒子的初始数据写入逻辑:
Future<void> getData() async {
  // 直接拿全局已经初始化完成的盒子实例
  final venueBox = Hive.box('venuesBox');
  List<Venue> storedVenues = List<Venue>.from(venueBox.values.toList());
  
  // 首次运行盒子为空时,从asset读取初始json数据写入Hive,后续启动直接读本地存储
  if (storedVenues.isEmpty) {
    final String response = await rootBundle.loadString('assets/venues.json');
    final data = await json.decode(response);
    storedVenues = List<Venue>.from(data["items"]);
    await venueBox.addAll(storedVenues);
  }

  setState(() {
    _venues = storedVenues;
  });
}
  1. 给列表增加加载状态判断,避免异步读数据时直接渲染空列表出现白屏,修改build方法中body部分逻辑:
@override
Widget build(BuildContext context) {
  return Scaffold(
    body: _venues.isEmpty 
      ? const Center(child: CircularProgressIndicator())
      : GroupedListView<Venue, String>(
          elements: _venues,
          groupBy: (Venue v) => v.venueGroup,
          groupComparator: (value1, value2) => value2.compareTo(value1),
          order: GroupedListOrder.DESC,
          useStickyGroupSeparators: true,
          separator: Divider(
            height: 1.0,
            color: Colors.grey,
          ),
          groupSeparatorBuilder: (String value) => Padding(
            padding: const EdgeInsets.all(0.0),
            child: Container(
              padding: const EdgeInsets.fromLTRB(10.0, 15.0, 10.0, 15.0),
              color: kMidBlueColour,
              child: Text(
                value.toUpperCase(),
                textAlign: TextAlign.center,
                style: const TextStyle(
                    fontSize: 26,
                    fontWeight: FontWeight.normal,
                    fontFamily: 'SanFranciscoDisplay',
                    color: Colors.white),
              ),
            ),
          ),
          itemBuilder: (c, Venue v) {
            return ListTile(
              contentPadding:
                  const EdgeInsets.symmetric(horizontal: 20.0, vertical: 10.0),
              leading: Hero(
                tag: v.venueName,
                child: Container(
                  child: Image.asset(
                    'images/venue1440/' + v.venueImage,
                    fit: BoxFit.contain,
                  ),
                ),
              ),
              title: Text(
                v.venueTitle.toString().toUpperCase(),
                style: TextStyle(
                  color: kMidBlueColour,
                  fontFamily: 'SanFranciscoDisplay',
                  fontSize: 20.0,
                ),
              ),
              subtitle: Text(
                v.venueAddress,
                style: TextStyle(
                  color: Color(0xFF4A4A49),
                  fontFamily: 'SanFranciscoDisplay',
                  fontSize: 18.0,
                ),
              ),
              trailing: const Icon(
                Icons.circle,
                color: Colors.grey,
                size: 50.0,
              ),
              visualDensity: const VisualDensity(horizontal: 4, vertical: 0),
              onTap: () {},
            );
          },
        ),
  );
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 00:18:20