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的差量刷新。

主要使用方式如下:

 

 

 

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= viewModel.getProducts(); 
       //第一个参数是LifecycleOwner接口的实现类(ActivityFragment等)
     //关联liveData与观察者,匿名的ObserverFragment的引用,当liveData更新
     //实际上是liveData->通知Observer->通知Fragment

        liveData.observe(this, new Observer>() {

        @Override

        public void onChanged(@Nullable List myProducts) {

            if (myProducts != null) {

                mBinding.setIsLoading(false);

                mProductAdapter.setProductList(myProducts);

            } else {

                mBinding.setIsLoading(true);

            }

            mBinding.executePendingBindings();

        }

    });

}
//在某个地方,比如网络上拉取到数据,执行
//viewModel.getProducts().setValue(….)即可通知Fragment更新
}

 

你可能感兴趣的:(Android官方实用类更新ViewDataBinding+DiffUtil+LiveData+ViewModel等)