背景
先简单介绍下背景,由于有国外客户使用MAUI进行Android开发,我们提供的SDK也需要适配MAUI平台,所以我的老大让我研究在MAUI平台开发Android应用Demo以及使用我们的SDK。
我们做应用开发时一般使用列表进行数据展示时,展示的数据内容一般包含有1个或多个信息。当其中一条数据的某个信息发生变化时,我们需要更新到UI上信息展示。这种情况下我们一般是找到数据发生改变的这条数据,将数据变化通知到UI去进行更新,但是MAUI的CollectionView仅支持增删的方式进行UI列表更新:
使用数据填充 CollectionView - .NET MAUI | Microsoft Learn
原先的解决方案
我原先的解决方案比较暴力,而且在体验上并不好。 我是先找到要更新的元素,获取它在数据源中的下标index,先删除再添加新的方式,下面给出一个简单的例子,仅做参考:
public ObservableCollection<DeviceModel> DeviceModels { get; private set; }
...
DeviceModels.RemoveAt(index);
DeviceModels.Insert(index, deviceModel);
这样会带来两个问题:一个是因为进行Remove和Insert操作都会发送属性更改通知,所以会有两次UI刷新,这样会使得列表抖动,体验上并不友好;第二个是因为多了的UI刷新也会影响到性能。
新的解决方案
将Model设置为可观察的就可解决这个问题,具体的解决方案是让Model实现INotifyPropertyChanged接口,例如:
public class DeviceModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler? PropertyChanged;
private string _address;
private string _name;
public string Address
{
get { return _address; }
set
{
_address = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Address)));
}
}
public string Name
{
get { return _name; }
set
{
_name = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Name)));
}
}
public DeviceModel()
{
}
}
这样的话就可以直接找到对应的要更新数据的元素更新其属性即可:
DeviceModels[index].Name = deviceModel.Name;
曾尝试的其它方案
我老大给我推了一个VirtualListView,让我研究一下可不可以解决这个问题。由于没能跑动VirtualListView库提供的demo以及提供的Readme介绍有限,我只能硬看代码。我研究了几天发现并不能解决,而且还发现使用VirtualListView的话进行数据更新得在UI线程进行,这就意味着如果在子线程中获取数据后得切换到UI线程中进行数据的添加,删除等,所以后续我还是放弃了使用VirtualListView。如果是我研究有问题,欢迎评论探讨。下面贴出VirtualListView的仓库地址: Maui.VirtualListView
参考
Maui开发 CollectionView 绑定后增删元素时UI会更新,修改属性时不会更新。-lfobb_dubo-ChinaUnix博客