Xamarin Forms 结合SQL实现条目删除时偶发重复显示问题排查
问题根因分析
该问题偶发的核心原因是异步操作时序不稳定、集合更新线程不安全两类问题叠加:
- 加载命令并发执行:删除事件回调中采用
_ = ExecuteLoadItemsCommand()的火并忘写法,无等待机制,短时间多次触发删除时会出现多个加载命令并发执行。此时可能出现后触发的加载先完成数据拉取,先触发的加载晚返回后重复添加数据的情况,导致数据源里出现重复条目。 - ObservableCollection跨线程操作:
ExecuteLoadItemsCommand中对Items的Clear、Add操作未强制在UI线程执行,当异步回调回到非UI线程时,CollectionView无法正确响应集合变更通知,会出现UI渲染和数据源不一致的视觉重复,手动刷新触发全量UI更新后才会恢复正常。 - SQLite连接多实例冲突:每次删除操作都新建
SQLiteAsyncConnection实例,多操作并发时可能出现删除操作还未落盘,加载命令就已读取到未删除的旧数据,看起来像删除失败出现重复条目。
修复方案
可按优先级选择以下修复措施:
优先推荐:优化删除逻辑,避免全量刷新
删除完成后直接从数据源移除对应条目,不需要重新拉取全量数据,性能更高且不会出现并发加载问题:
private async Task OnDeleteItem(Item selectedItem) { await LocalDatabaseService.DeleteItem(selectedItem); // 强制在UI线程操作集合,保证变更能被CollectionView正确响应 await MainThread.InvokeAsync(() => { if (Items.Contains(selectedItem)) { Items.Remove(selectedItem); } }); }
调整后可以删除原删除事件回调中的加载逻辑,不需要再触发全量数据刷新。
基础修复:修复加载命令的并发和线程安全问题
如果需要保留全量刷新逻辑,需给加载命令加防重入锁,并强制集合操作在UI线程执行:
private bool _isLoading; async Task ExecuteLoadItemsCommand() { if (_isLoading) return; _isLoading = true; IsBusy = true; try { await MainThread.InvokeAsync(() => Items.Clear()); var items = await LocalDatabaseService.GetAllItems(); await MainThread.InvokeAsync(() => { foreach (var item in items) { Items.Add(item); } }); } catch (Exception ex) { Debug.WriteLine(ex); } finally { IsBusy = false; _isLoading = false; } }
底层优化:SQLite连接改为单例模式
避免多连接并发导致的数据读写不一致问题:
// LocalDatabaseService中添加单例连接逻辑 private static SQLiteAsyncConnection _db; private static SQLiteAsyncConnection GetDbConnection() { if (_db == null) { var databasePath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), "MyData3.db"); _db = new SQLiteAsyncConnection(databasePath); } return _db; } public async Task DeleteItem(Item item) { var db = GetDbConnection(); await db.DeleteAsync(item); OnDeletedItem?.Invoke(); }
可选优化:调整CollectionView缓存策略
避免cell复用导致的视觉重复,在XAML中添加缓存策略属性:
<CollectionView x:Name="ItemsListView" ItemsSource="{Binding Items}" SelectionMode="None" CachingStrategy="RecycleElementAndDataTemplate">
内容的提问来源于stack exchange,提问作者TinTan19
相关产品推荐
相关产品推荐

