写点什么

分享一个 RecyclerView 中定点刷新的小技巧,android 音频框架

用户头像
Android架构
关注
发布于: 刚刚

class ItemViewModel constructor( val data:String){


//not


//val count = data


//val liked = false


//should


val count = ObservableField<String>(data)


val liked = ObservableBoolean()


}


//partial_list_item.xml


<?xml version="1.0" encoding="utf-8"?>


<layout>


<data>


<variable


name="item"


type="io.ditclear.app.partial.PartialItemViewModel" />


<variable


name="presenter"


type="io.ditclear.bindingadapterx.ItemClickPresenter" />


</data>


<androidx.constraintlayout.widget.ConstraintLayout


android:onClick="@{(v)->presenter.onItemClick(v,item)}"



<TextView


android:text="@{item.count}" />


<ImageView


android:src="@{item.liked?@drawable/ic_action_liked:@drawable/ic_action_unlike}"/>


</androidx.constraintlayout.widget.ConstraintLayout>


</layout>


当 UI 需要改变时,改变 ItemViewModel 的数据即可。


//activity


override fun onItemClick(v: View, item: PartialItemViewModel) {


item.toggle()


}


// ItemViewModle


fun toggle(){


liked.set(!liked.get())


count.set("{if (liked.get()) "liked" else ""}")


}


至于为什么?这就要说到 DataBinding 更新 UI 的原理了。


#/? ?DataBinding 更新 UI 原理? ?/


当我们在项目中运用 DataBinding,并将 xml 文件转换为 DataBinding 形式之后。经过编译 build,会生成相应的 binding 文件,比如 partial_list_item.xml 就会生成对于的 PartialListItemBinding 文件,这是一个抽象类,还会有一个 PartialListItemBindingImpl 实现类实现具体的渲染 UI 的方法 executeBindings。


当数据有改变的时候,就会重新调用 executeBindings 方法,更新 UI,那怎么做到的呢?



我们先来看 PartialListItemBinding 的构造方法.


public abstract class PartialListItemBinding extends ViewDataBinding {


@NonNull


public final ImageView imageView;


@Bindable


protected PartialItemViewModel mItem;


@Bindable


protected ItemClickPresenter mPresenter;


protected PartialListItemBinding(DataBindingComponent _bindingComponent, View _root,


int _localFieldCount, ImageView imageView) {


//调用父类的构造方法


super(_bindingComponent, _root, _localFieldCount);


this.imageView = imageView;


}


//...


}


调用了父类 ViewDataBinding 的构造方法,并传入了三个参数,这里看第三个参数_localFieldCount,它代表 xml 中存在几个 ObservableField 形式的数据,继续追踪.


protected ViewDataBinding(DataBindingComponent bindingComponent, View root, int localFieldCount) {


this.mBindingComponent = bindingComponent;


//考点 1


this.mLocalFieldObservers = new ViewDataBinding.WeakListener[localFieldCount];


this.mRoot = root;


if (Looper.myLooper() == null) {


throw new IllegalStateException("DataBinding must be created in view's UI Thread");


} else {


if (USE_CHOREOGRAPHER) {


//考点 2


this.mChoreographer = Choreographer.getInstance();


this.mFrameCallback = new FrameCallback() {


public void doFrame(long frameTimeNanos) {


ViewDataBinding.this.mRebindRunnable.run();


}


};


} else {


this.mFrameCallback = null;


this.mUIThreadHandler = new Handler(Looper.myLooper());


}


}


}


通过观察,发现其根据 localFieldCount 初始化了一个 WeakListener 数组,名为 mLocalFieldObservers。另一个重点是初始化了一个 mFrameCallback,在回调中执行了 mRebindRunnable.run。


当生成的 PartialListItemBindingImpl 对象调用 executeBindings 方法时,通过 updateRegistration 会对 mLocalFieldObservers 数组中的内容进行赋值。



随之生成的是相应的 WeakPropertyListener,来看看它的定义。


private static class WeakPropertyListener extends Observable.OnPropertyChangedCallback


implements ObservableReference<Observable> {


final WeakListener<Observable> mListener;


public WeakPropertyListener(ViewDataBinding binder, int localFieldId) {


mListener = new WeakListener<Observable>(binder, localFieldId, this);


}


//...


@Override


public void onPropertyChanged(Observable sender, int propertyId) {


ViewDataBinding binder = mListener.getBinder();


if (binder == null) {


return;


}


Observable obj = mListener.getTarget();


if (obj != sender) {


return; // notification from the wrong object?


}


//划重点


binder.handleFieldChange(mListener.mLocalFieldId, sender, propertyId);


}


}


当 ObservableField 的值有改变的时候,onPropertyChanged 会被调用,然后就会回调 binder(即 binding 对象)的 handleFieldChange 方法,继续观察。


private void handleFieldChange(int mLocalFieldId, Object object, int fieldId) {


if (!this.mInLiveDataRegisterObserver) {


boolean result = this.onFieldChange(mLocalFieldId, object, fieldId);


if (result) {


this.request


《Android学习笔记总结+最新移动架构视频+大厂安卓面试真题+项目实战源码讲义》
浏览器打开:qq.cn.hn/FTe 免费领取
复制代码


Rebind();

用户头像

Android架构

关注

还未添加个人签名 2021.10.31 加入

还未添加个人简介

评论

发布
暂无评论
分享一个RecyclerView中定点刷新的小技巧,android音频框架