Flutter中SQLite数据变动无用户交互如何重建UI?页面重访触发刷新方法是什么
问题解答
一、SQLite数据库变动时自动刷新UI的方案
你可以从以下3种方案中按需选择:
- 方案1:使用事件总线(轻量无侵入,适合小型项目)
步骤如下:- 全局定义事件类和事件总线实例
// 全局位置定义 class BookmarkTableChangedEvent {} final eventBus = EventBus(); // 安装eventBus依赖包后直接初始化即可- 在所有修改Bookmark表的操作完成后发送变更事件,比如你现有代码里的删除方法:
deleteAllPersons() async { final db = await database; await db.delete("Bookmark"); // 发送表变更事件 eventBus.fire(BookmarkTableChangedEvent()); } deletePersonWithId(int id) async { final db = await database; final res = await db.delete("Bookmark", where: "id = ?", whereArgs: [id]); eventBus.fire(BookmarkTableChangedEvent()); return res; } // 注意:其他所有插入、更新Bookmark表的逻辑位置,都需要加上发送事件的代码- 在当前页面订阅事件,收到事件后触发刷新,同时优化原有FutureBuilder逻辑,避免每次build重复查询数据库
class _FavouriteScreenState extends State<FavouriteScreen> { StreamSubscription? _eventSub; late Future<List<Bookmark>> _bookmarkFuture; @override void initState() { super.initState(); _bookmarkFuture = getAllPersons(); // 订阅数据库变更事件 _eventSub = eventBus.on<BookmarkTableChangedEvent>().listen((_) { setState(() { _bookmarkFuture = getAllPersons(); }); }); } @override void dispose() { _eventSub?.cancel(); // 销毁时取消订阅,防止内存泄漏 super.dispose(); } // 原有build方法里的FutureBuilder的future参数改为_bookmarkFuture即可 } - 方案2:使用Drift(原Moor)数据库封装库(原生支持数据流,首选)
该库是sqflite的上层封装,直接支持返回Stream监听表变动,你只需要把查询逻辑改成返回Stream,把FutureBuilder替换为StreamBuilder,数据库有任何变动都会自动刷新UI,不需要手动发送事件。 - 方案3:用全局状态管理(适合中大型项目)
用Provider、Riverpod、Bloc等状态管理工具封装数据库操作,把书签列表的状态全局暴露,页面监听状态变化自动触发UI更新。
二、回到当前页面时触发刷新的实现方式
Flutter原生State的生命周期里没有默认的「回到页面」回调,需要通过对应工具实现:
- 如果你是通过
Navigator.push跳转到下一级页面,再返回当前页面,可以用RouteObserver监听回调:- 全局定义RouteObserver实例
final RouteObserver<ModalRoute<void>> routeObserver = RouteObserver<ModalRoute<void>>();- 在MaterialApp里配置导航观察者
MaterialApp( navigatorObservers: [routeObserver], // 其余原有配置不变 )- 当前页面的State混入
RouteAware,监听didPopNext回调(该回调会在其他页面pop回到当前页面时触发)
class _FavouriteScreenState extends State<FavouriteScreen> with RouteAware { @override void didChangeDependencies() { super.didChangeDependencies(); routeObserver.subscribe(this, ModalRoute.of(context)!); } @override void didPopNext() { // 回到当前页面,在这里执行刷新逻辑 setState(() { _bookmarkFuture = getAllPersons(); }); super.didPopNext(); } @override void dispose() { routeObserver.unsubscribe(this); super.dispose(); } } - 如果你是通过BottomNavigationBar切换Tab回到该页面,直接在Tab切换的监听逻辑里调用对应页面的刷新方法即可。
内容的提问来源于stack exchange,提问作者Samuel T
相关产品推荐
相关产品推荐

