Android官方实用类更新ViewDataBinding+DiffUtil+LiveData+ViewModel等

ViewDataBinding 可用于绑定Activity/Fragement等,类似于ButterKnife,好处在于把Activity的逻辑与布局的实现彻底分离,布局相关逻辑全部转移到XXXViewdataBindng中。
而且DataBinding比ButterKnife效率高

DiffUtil DiffUtil是support-v7:24.2.0推出的工具,用来寻找新旧两个数据集的最小变化量,主要使用场景是recycleView的更新,针对RecycleView全局更新的主要缺点:

  1. 不会触发RecyclerView的动画(删除、新增、位移、change动画)
  2. 性能较低,毕竟是无脑的刷新了一遍整个RecyclerView , 极端情况下:新老数据集一模一样,效率是最低的。
通过DiffUtil能轻松实现recycleView的差量刷新。
主要使用方式如下:
【Android官方实用类更新ViewDataBinding+DiffUtil+LiveData+ViewModel等】


DiffUtil.DiffResult result = DiffUtil.calculateDiff(new DiffUtil.Callback() {
@Override
public int getOldListSize() {
return mProductList.size();
}

@Override
public int getNewListSize() {
return productList.size();
}

@Override
public boolean areItemsTheSame(int oldItemPosition, int newItemPosition) {//通过唯一标识判断是否同一数据
return mProductList.get(oldItemPosition).getId() ==
productList.get(newItemPosition).getId();
}

@Override
public boolean areContentsTheSame(int oldItemPosition, int newItemPosition) {//若是同一数据,再比较它内部有没有更新
Product newProduct = productList.get(newItemPosition);
Product oldProduct = mProductList.get(oldItemPosition);
return newProduct.getId() == oldProduct.getId()
&& Objects.equals(newProduct.getDescription(), oldProduct.getDescription())
&& Objects.equals(newProduct.getName(), oldProduct.getName())
&& newProduct.getPrice() == oldProduct.getPrice();
//上面一般情况可以在在实体类中实现equal接口,然后直接return o1.equals(o2)
}
});
mProductList = productList;
result.dispatchUpdatesTo(this);

使用以上的方式可以通过diffResult.dispatchUpdatesTo(adapter)函数实现刷新指定项,如果想做得更细,只刷新指定项中某个textView,imageView等也是可以,主要通过以下两个接口实现:
DiffUtil.Callback
public Object getChangePayload(int oldItemPosition, int newItemPosition)
RecyclerView.Adapter
public void onBindViewHolder(VH holder, int position, List payloads)
当一个item中包含多个view,比如item中有图片但我只想刷新某个textView,这种方式还是能提高性能的,这里不细讲。

LivaData LiveData是一个可被观察的数据持有类,与一般的Observer不同的是,LiveData能意识到应用程序组件的生命周期变化,其优点主要有:
·确保UI符合数据状态
LiveData遵循观察者模式。 当生命周期状态改变时,LiveData会向Observer发出通知。 您可以把更新UI的代码合并在这些Observer对象中。不必去考虑导致数据变化的各个时机,每次数据有变化,Observer都会去更新UI。
·没有内存泄漏
Observer会绑定具有生命周期的对象,并在这个绑定的对象被销毁后自行清理。
·不会因停止Activity而发生崩溃
如果Observer的生命周期处于非活跃状态,例如在后退堆栈中的Activity,就不会收到任何LiveData事件的通知。
·不需要手动处理生命周期
UI组件只需要去观察相关数据,不需要手动去停止或恢复观察。LiveData会进行自动管理这些事情,因为在观察时,它会感知到相应组件的生命周期变化。
·始终保持最新的数据
如果一个对象的生命周期变到非活跃状态,它将在再次变为活跃状态时接收最新的数据。 例如,后台Activity在返回到前台后立即收到最新数据。
·正确应对配置更改
如果一个Activity或Fragment由于配置更改(如设备旋转)而重新创建,它会立即收到最新的可用数据。
您可以使用单例模式扩展LiveData对象并包装成系统服务,以便在应用程序中进行共享。LiveData对象一旦连接到系统服务,任何需要该资源的Observer都只需观察这个LiveData对象。
一般用法:

public class ProductListFragment extends Fragment {

…..

private void subscribeUi(ProductListViewModel viewModel) {// Update the list when the data changes

LiveData liveData= https://www.it610.com/article/viewModel.getProducts();

//第一个参数是LifecycleOwner接口的实现类(Activity,Fragment等)

//关联liveData与观察者,匿名的Observer有Fragment的引用,当liveData更新

//实际上是liveData->通知Observer->通知FragmentliveData.observe(this, new Observer() {@Overridepublic void onChanged(@Nullable List myProducts) {if (myProducts != null) {mBinding.setIsLoading(false); mProductAdapter.setProductList(myProducts); } else {mBinding.setIsLoading(true); }mBinding.executePendingBindings(); }}); }

//在某个地方,比如网络上拉取到数据,执行

//viewModel.getProducts().setValue(….)即可通知Fragment更新

}


    推荐阅读