Flutter中无需使用FutureBuilder,能否监听Hive数据库的数据变化?
解决Flutter Hive单例结合Provider实现自动数据监听(无需FutureBuilder)
核心思路
把Hive单例助手类改造为ChangeNotifier子类,在每次修改Hive数据后调用notifyListeners()触发UI刷新;同时在应用启动时完成Hive初始化,通过Provider全局注入助手类实例,UI层通过Consumer或Provider.of监听数据变化。
1. 改造Hive单例助手类
保留单例模式的同时继承ChangeNotifier,在增删改数据的方法中添加通知逻辑:
import 'package:hive/hive.dart'; import 'package:flutter/foundation.dart'; // 示例数据模型类 part 'your_model.g.dart'; @HiveType(typeId: 0) class YourModel extends HiveObject { @HiveField(0) final String id; @HiveField(1) final String content; YourModel({required this.id, required this.content}); } class HiveHelper extends ChangeNotifier { static final HiveHelper _instance = HiveHelper._internal(); late Box<YourModel> _box; factory HiveHelper() => _instance; HiveHelper._internal() { // 这里依赖main函数中提前打开的box _box = Hive.box<YourModel>('your_data_box'); } // 获取数据列表 List<YourModel> get dataList => _box.values.toList(); // 添加数据后通知UI刷新 void addItem(YourModel item) { _box.add(item); notifyListeners(); } // 删除数据后通知UI刷新 void deleteItem(int index) { _box.deleteAt(index); notifyListeners(); } // 修改数据后通知UI刷新 void updateItem(int index, YourModel newItem) { _box.putAt(index, newItem); notifyListeners(); } }
2. 应用启动时完成Hive初始化
在main函数中先完成Hive初始化、适配器注册、box打开,再启动应用,避免使用FutureBuilder:
import 'package:flutter/material.dart'; import 'package:hive/hive.dart'; import 'package:hive_flutter/hive_flutter.dart'; import 'package:provider/provider.dart'; void main() async { WidgetsFlutterBinding.ensureInitialized(); // 初始化Hive await Hive.initFlutter(); // 注册数据模型适配器(需提前运行build_runner生成) Hive.registerAdapter(YourModelAdapter()); // 打开目标box await Hive.openBox<YourModel>('your_data_box'); runApp( ChangeNotifierProvider( create: (context) => HiveHelper(), child: const MyApp(), ), ); } class MyApp extends StatelessWidget { const MyApp({super.key}); @override Widget build(BuildContext context) { return MaterialApp( title: 'Hive + Provider Demo', home: const DataListPage(), ); } }
3. UI层监听数据变化
使用Consumer组件监听HiveHelper的变化,自动刷新UI:
class DataListPage extends StatelessWidget { const DataListPage({super.key}); @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: const Text('数据列表')), body: Consumer<HiveHelper>( builder: (context, hiveHelper, child) { final data = hiveHelper.dataList; if (data.isEmpty) { return const Center(child: Text('暂无数据')); } return ListView.builder( itemCount: data.length, itemBuilder: (context, index) { final item = data[index]; return ListTile( title: Text(item.content), trailing: IconButton( icon: const Icon(Icons.delete), onPressed: () => hiveHelper.deleteItem(index), ), ); }, ); }, ), floatingActionButton: FloatingActionButton( onPressed: () { // 添加测试数据 final newItem = YourModel( id: DateTime.now().millisecondsSinceEpoch.toString(), content: '新数据 ${DateTime.now().minute}:${DateTime.now().second}', ); // 无需监听变化,所以listen设为false Provider.of<HiveHelper>(context, listen: false).addItem(newItem); }, child: const Icon(Icons.add), ), ); } }
关键注意事项
- 运行
flutter packages pub run build_runner build生成Hive模型的适配器代码,否则无法正常序列化数据。 - 确保在
main函数中完成Hive的所有初始化操作(init、注册适配器、打开box),避免UI层出现未初始化错误。 - 在按钮点击等无需监听变化的场景中,使用
Provider.of<HiveHelper>(context, listen: false)避免不必要的UI重建。
内容的提问来源于stack exchange,提问作者Kyaw Gyi
相关产品推荐
相关产品推荐

