本文将介绍android-从LiveData.observe()向适配器添加项目的最佳实践的详细情况,特别是关于androidrecyclerview适配器的相关信息。我们将通过案例分析、数据研究等多
本文将介绍android-从LiveData.observe()向适配器添加项目的最佳实践的详细情况,特别是关于android recyclerview适配器的相关信息。我们将通过案例分析、数据研究等多种方式,帮助您更全面地了解这个主题,同时也将涉及一些关于android -------- LiveDataBus的使用、Android BaseAdapter DataSetObserver通知机制、Android Data Binding 系列 (二) -- Binding 与 Observer 实现原理、Android jetpack 之 LiveData的知识。
本文目录一览:- android-从LiveData.observe()向适配器添加项目的最佳实践(android recyclerview适配器)
- android -------- LiveDataBus的使用
- Android BaseAdapter DataSetObserver通知机制
- Android Data Binding 系列 (二) -- Binding 与 Observer 实现原理
- Android jetpack 之 LiveData
android-从LiveData.observe()向适配器添加项目的最佳实践(android recyclerview适配器)
我有DAO方法返回了LiveData< List< Category>> ;:
LiveData<List<Category>> listLiveData = categoryDao.getAll();
之后,我需要将此数据设置为我的适配器:
listLiveData.observe(this, categories -> {
if (categories == null || categories.isEmpty()) {
price.setVisibility(View.VISIBLE);
recyclerView.setVisibility(View.INVISIBLE);
} else {
categoryAdapter = new CategoryAdapter(categories);
categoryAdapter.setonItemClickListener(new ClickHandler());
recyclerView.setAdapter(categoryAdapter);
}
});
如果数据库中没有数据,则显示更新按钮(从服务器获取数据并插入到数据库中).
如果我有数据,我将创建适配器并为其设置数据.
之后,如果我向数据库插入一些类别,则会得到以下信息:
>触发观察方法并获取所有类别
>使用此数据创建新的适配器
我认为这是非常不好的做法(为更新每个项目创建一个新的适配器),我可以采取一些措施:
>更改我的适配器并添加方法addData(List< Category> Categories);
在onCreateView中,我创建适配器:categoryAdapter = new CategoryAdapter(new ArrayList());
然后当我在观察方法中获取数据时,将其添加到适配器中:
adapter.addData(categories);
并在addData方法中循环检查每个项目,如果不存在,则添加到列表并通知数据.
>变更方法
实时数据listLiveData = categoryDao.getAll();
至
LiveData<Category> category = categoryDao.getLast();
并添加此项以观察方法.但是我有2个问题:1-如何首先添加所有数据?我必须实现2个方法getAll(调用创建适配器)和getLast(调用数据库中的每个插入). 2.如何编写此getLast方法?
>正确的方法,你会建议我:)
解决方法:
>第一步是正确的,您应该仅在Fragment或Activity的生命周期中创建适配器一次,并在需要更改数据集时将值(列表)设置为adapter.
>您应该使用getAll()方法,这是最佳实践,因为您的数据在本地数据库中,并且不需要花费更长的时间.如果数据集较长,则应使用分页,其中仅限制为no.一次提取的商品数量.这可以通过在sqlite中使用LIMIT子句查询来实现.
>然后使用notifyDatasetChanged()方法.如果要为新插入的项目显示平滑的动画,请使用DiffUtil类比较列表并相应地通知适配器.
要知道如何使用DiffUtil,请检查https://medium.com/@iammert/using-diffutil-in-android-recyclerview-bdca8e4fbb00
希望这可以帮助.
android -------- LiveDataBus的使用
LiveData是17年GoogleIO大会上提出来的一个新技术。相对于通信总线类型的框架EventBus和RxBus来说,它更简单,更简洁、更解耦。
LiveEventBus是一款Android消息总线,基于LiveData,具有生命周期感知能力,支持Sticky,支持AndroidX,支持跨进程,支持跨APP
LiveDataBus优点
LiveDataBus的实现及其简单
相对EventBus复杂的实现,LiveDataBus只需要一个类就可以实现
LiveDataBus可以减小APK包的大小
LiveDataBus只依赖Android官方组件LiveData,本身实现只一个类。EventBus 57Kb、RxJava 2.2M
LiveDataBus 依赖方支持更好
LiveDataBus只依赖Android官方组件LiveData,相比RxBus依赖的RxJava和RxAndroid,依赖方支持更好
LiveDataBus具有生命周期感知
LiveDataBus具有生命周期感知,在Android系统中使用调用者不需要调用反注册,相比EventBus和RxBus使用更为方便,并且没有内存泄漏风险。
LiveEventBus的特点
生命周期感知,消息随时订阅,自动取消订阅
支持Sticky粘性消息
支持AndroidX
支持跨进程通信
支持跨APP通信
支持设置LifecycleObserver(如Activity)接收消息的模式:
1.整个生命周期(从onCreate到onDestroy)都可以实时收到消息
2.激活状态(Started)可以实时收到消息,非激活状态(Stoped)无法实时收到消息,需等到Activity重新变成激活状态,方可收到消息
在工程中引用
implementation ''com.jeremyliao:live-event-bus:1.4.2''
配置
在 Application.onCreate 方法中配置:
LiveEventBus.get()
.config()
.supportBroadcast(this)
.lifecycleObserverAlwaysActive(true);
具有生命周期感知能力,LifecycleOwner销毁时自动取消订阅,不需要调用removeObserver
保证 with() 中的key值相同,(注册/接收)和发起通信
注册:
LiveEventBus.get().with("LiveDataBusDemo1",String.class).observe(this, new Observer<String>() {
@Override
public void onChanged(@Nullable String s) {
Log.i("aaa",s);
}
});
发起通信
LiveEventBus.get().with("LiveDataBusDemo1").post("LiveDataBus1");
以Forever模式订阅和取消订阅消息,Forever模式订阅消息,需要手动调用removeObserver取消订阅
注册
private Observer<String> observer = new Observer<String>() {
@Override
public void onChanged(@Nullable String s) {
Log.i("aaa",s);
textView.setText("observeForever注册的观察者收到消息: " + s);
}
};
LiveEventBus.get()
.with("LiveDataBusDemo2", String.class)
.observeForever(observer);
发起通信
LiveEventBus.get().with("LiveDataBusDemo2").post("LiveDataBus2");
手动取消订阅消息
LiveEventBus.get()
.with("LiveDataBusDemo2", String.class)
.removeObserver(observer);
Sticky模式(可以接收 前面/未注册之前 发起通信的信息)
支持在订阅消息的时候设置Sticky模式,这样订阅者可以接收到之前发送的消息,当然也支持后面发送的信息
以Sticky模式订阅消息,具有生命周期感知能力,LifecycleOwner销毁时自动取消订阅,不需要调用removeObserver
注册
LiveEventBus.get()
.with("LiveDataBusDemo3", String.class)
.observeSticky(this, new Observer<String>() {
@Override
public void onChanged(@Nullable String s) {
Log.i("aaa",s);
textView.setText("observeSticky注册的观察者收到消息: " + s);
}
});
发起通信(你可以在注册之前和注册之后分辨发起通知看效果)
LiveEventBus.get().with("LiveDataBusDemo3").post("LiveDataBus3");
observeStickyForever,Forever模式订阅消息,需要手动调用removeObserver取消订阅,和上面的一样
注册
private Observer<String> observer = new Observer<String>() {
@Override
public void onChanged(@Nullable String s) {
Log.i("aaa",s);
textView.setText("observeStickyForever注册的观察者收到消息: " + s);
}
};
LiveEventBus.get()
.with("LiveDataBusDemo4", String.class)
.observeStickyForever(observer);
发起通信
LiveEventBus.get().with("LiveDataBusDemo4").post("LiveDataBus4");
手动取消订阅消息
LiveEventBus.get()
.with("LiveDataBusDemo4", String.class)
.removeObserver(observer);
混淆规则
-dontwarn com.jeremyliao.liveeventbus.**
-keep class com.jeremyliao.liveeventbus.** { *; }
-keep class android.arch.lifecycle.** { *; }
-keep class android.arch.core.** { *; }
参考文档:
https://github.com/JeremyLiao/LiveEventBus
Android BaseAdapter DataSetObserver通知机制
一.BaseAdapter内部设有观察者机制
public abstract class BaseAdapter implements ListAdapter, SpinnerAdapter {
private final DataSetObservable mDataSetObservable = new DataSetObservable();
public void registerDataSetObserver(DataSetObserver observer) {
mDataSetObservable.registerObserver(observer);
}
public void unregisterDataSetObserver(DataSetObserver observer) {
mDataSetObservable.unregisterObserver(observer); //刷新界面和数据
}
public void notifyDataSetChanged() {
mDataSetObservable.notifyChanged(); //刷新界面
}
public void notifyDataSetInvalidated() {
mDataSetObservable.notifyInvalidated();
}
/**
*一下省略到一大片成员变量
*方法数(何止一二个)
*变量(反正已知的不多)
*/
}
其中我们看到了
--观察者集合容器
DataSetObservable
--观察者
public abstract class DataSetObserver {
public void onChanged() {
// Do nothing
}
public void onInvalidated() {
// Do nothing
}
}
二,应用
首先:这些观察者普遍存在于BaseAdapter,FragmentPagerAdapter,PagerAdapter,RecyclerView.Adapter中,主要是为了配合适配器更新数据
应用一.RecylerView中的EmptyView
public class RecyclerViewEmptySupport extends RecyclerView {
private View emptyView;
private AdapterDataObserver emptyObserver = new AdapterDataObserver() {
@Override
public void onChanged() {
Adapter<?> adapter = getAdapter();
if(adapter != null && emptyView != null) {
if(adapter.getItemCount() == 0) {
emptyView.setVisibility(View.VISIBLE);
RecyclerViewEmptySupport.this.setVisibility(View.GONE);
}
else {
emptyView.setVisibility(View.GONE);
RecyclerViewEmptySupport.this.setVisibility(View.VISIBLE);
}
}
}
};
public RecyclerViewEmptySupport(Context context) {
super(context);
}
public RecyclerViewEmptySupport(Context context, AttributeSet attrs) {
super(context, attrs);
}
public RecyclerViewEmptySupport(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
@Override
public void setAdapter(Adapter adapter) {
super.setAdapter(adapter);
if(adapter != null) {
adapter.registerAdapterDataObserver(emptyObserver);
}
emptyObserver.onChanged();
}
public void setEmptyView(View emptyView) {
this.emptyView = emptyView;
}}
xml
<com.maff.utils.RecyclerViewEmptySupport android:id="@+id/list1"
android:layout_height="match_parent"
android:layout_width="match_parent"
/><TextView android:id="@+id/list_empty"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Empty"
/>
Activity
RecyclerViewEmptySupport list =
(RecyclerViewEmptySupport)rootView.findViewById(R.id.list1);
list.setLayoutManager(new LinearLayoutManager(context));
list.setEmptyView(rootView.findViewById(R.id.list_empty));
应用二,我们可以通过注册观察者,判断数据变化我们可以减少判断,特别在加载网络数据的时候
应用三,我们可以在数据变化时开始某一类动画
Android Data Binding 系列 (二) -- Binding 与 Observer 实现原理
写在前面
上篇文章 Android Data Binding 系列 (一) -- 详细介绍与使用 介绍了 Data Binding
的基础及其用法,本文接上篇,结合 DataBindingDemo 来学习下 Data Binding
的实现。
绑定实现
Activity 在 inflate layout 时,通过 DataBindingUtil 来生成绑定,从代码看,是遍历 contentView 得到 View 数组对象,然后通过数据绑定 library 生成对应的 Binding 类,含 Views、变量、listeners 等。生成类位于 build/intermediates/classes/debug/...package.../databinding/xxx.java
下,具体如何生成这里暂不作深入。
绑定过程
- 首先,会在父类(ViewDataBinding)中实例化回调或 Handler,用于之后的绑定操作;
private static final boolean USE_CHOREOGRAPHER = SDK_INT >= 16;
if (USE_CHOREOGRAPHER) {
mChoreographer = Choreographer.getInstance();
mFrameCallback = new Choreographer.FrameCallback() {
@Override
public void doFrame(long frameTimeNanos) {
mRebindRunnable.run();
}
};
} else {
mFrameCallback = null;
mUIThreadHandler = new Handler(Looper.myLooper());
}
- 接着,通过调用
mapBindings(...)
遍历布局以获得包含 bound、includes、ID Views 的数组对象,再依次赋给对应 View
final Object[] bindings = mapBindings(bindingComponent, root, 3, sIncludes, sViewsWithIds);
this.mboundView0 = (android.widget.LinearLayout) bindings[0];
this.mboundView0.setTag(null);
- 然后,调用
invalidateAll() -> requestRebind() -> ... -> mRebindRunnable.run() -
执行 Runnable
// 用于动态重新绑定 Views
private final Runnable mRebindRunnable = new Runnable() {
@Override
public void run() {
synchronized (this) {
mPendingRebind = false;
}
.....
executePendingBindings();
}
};
- 最后,通过该 Runnable 会执行到
executePendingBindings() -> ... -> executeBindings()
,在这里会执行绑定相关操作。
@Override
protected void executeBindings() {
long dirtyFlags = 0;
synchronized(this) {
dirtyFlags = mDirtyFlags; // mDirtyFlags 变量更新的标志
mDirtyFlags = 0;
}
.....
}
设置变量 (数据对象)
普通 Java bean 对象
- 首先,通过 mDirtyFlags 标识变量 (所有变量共用)
synchronized(this) {
mDirtyFlags |= 0x1L;
}
- 然后,调用
notifyPropertyChanged(...)
来通知更新(若有回调)
public void notifyPropertyChanged(int fieldId) {
if (mCallbacks != null) {
mCallbacks.notifyCallbacks(this, fieldId, null);
}
}
- 最后,调用
requestRebind() -> ... -> executeBindings()
再次执行绑定操作,将数据更新到 Views 上
@Override
protected void executeBindings() {
long dirtyFlags = 0;
synchronized(this) {
dirtyFlags = mDirtyFlags;
mDirtyFlags = 0;
}
.....
}
Observable 对象
- 在设置变量时,会先调用
updateRegistration(..)
注册一个 Observable 对象的监听
public void setContact(com.connorlin.databinding.model.ObservableContact contact) {
updateRegistration(0, contact);
this.mContact = contact;
synchronized(this) {
mDirtyFlags |= 0x1L;
}
notifyPropertyChanged(BR.contact);
super.requestRebind();
}
- 其他步骤同普通 Java bean 对象
ObservableFields 对象
-
前期步骤同普通 Java Bean 对象
-
与 Observable 对象不同的是,Observable 对象的监听是在
executeBindings()
中注册的
@Override
protected void executeBindings() {
long dirtyFlags = 0;
synchronized(this) {
dirtyFlags = mDirtyFlags;
mDirtyFlags = 0;
}
...
if ((dirtyFlags & 0xfL) != 0) {
if ((dirtyFlags & 0xdL) != 0) {
if (contact != null) {
// read contact.mName
mNameContact = contact.mName;
}
updateRegistration(0, mNameContact);
if (mNameContact != null) {
// read contact.mName.get()
mNameContact1 = mNameContact.get();
}
}
...
}
...
}
注册 Observable 对象监听
- 入口
updateRegistration(0, contact)
:
protected boolean updateRegistration(int localFieldId, Observable observable) {
return updateRegistration(localFieldId, observable, CREATE_PROPERTY_LISTENER);
}
private boolean updateRegistration(int localFieldId, Object observable,
CreateWeakListener listenerCreator) {
...
// 确保不重复监听,先移除再添加观察监听
unregisterFrom(localFieldId);
registerTo(localFieldId, observable, listenerCreator);
return true;
}
protected void registerTo(int localFieldId, Object observable,
CreateWeakListener listenerCreator) {
if (observable == null) {
return;
}
// 创建对象监听并存到mLocalFieldObservers中
WeakListener listener = mLocalFieldObservers[localFieldId];
if (listener == null) {
// CREATE_PROPERTY_LISTENER -> create(...)
listener = listenerCreator.create(this, localFieldId);
mLocalFieldObservers[localFieldId] = listener;
}
// 将监听绑定到Observable对象上
listener.setTarget(observable);
}
每个 Observable 对象都会添加一个观察监听,保存在数组 mLocalFieldObservers
中,并以 localFieldId
索引。
- CREATE_PROPERTY_LISTENER 为何物?
private static final CreateWeakListener CREATE_PROPERTY_LISTENER = new CreateWeakListener() {
@Override
public WeakListener create(ViewDataBinding viewDataBinding, int localFieldId) {
// 返回从WeakPropertyListener实例中获取的监听器(WeakListener)
return new WeakPropertyListener(viewDataBinding, localFieldId).getListener();
}
}
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 WeakListener<Observable> getListener() {
return mListener;
}
@Override
public void addListener(Observable target) {
// WeakPropertyListener 继承于 Observable.OnPropertyChangedCallback,
// 所以 this 其实就是 Observable对象的属性监听器
target.addOnPropertyChangedCallback(this);
}
...
}
private static class WeakListener<T> extends WeakReference<ViewDataBinding> {
private final ObservableReference<T> mObservable;
protected final int mLocalFieldId;
private T mTarget;
...
public void setTarget(T object) {
unregister();
mTarget = object;
if (mTarget != null) {
// mObservable 是上面的 WeakPropertyListener对象
// mTarget 是绑定到listener上得Observable对象
mObservable.addListener(mTarget);
}
}
...
}
CREATE_PROPERTY_LISTENER 实际上只是一个接口实例,注册时会调用它的 create()
方法创建一个弱引用 listener,它的作用是将 listener 绑定到 Observable 对象上, 绑定时,会调用 listener.setTarget(...)
将 Observable 对象传给 WeakPropertyListener
实例,然后,WeakPropertyListener
会为 Observable 对象添加 OnPropertyChangedCallback
。
- addOnPropertyChangedCallback 实现
addOnPropertyChangedCallback 在 BaseObservable 中实现,首先会实例化一个 PropertyChangeRegistry
对象,同时创建一个用来通知 Observable 对象重新绑定更新的回调 CallbackRegistry.NotifierCallback
。然后将 OnPropertyChangedCallback
添加到 PropertyChangeRegistry 的回调列表中
@Override
public synchronized void addOnPropertyChangedCallback(OnPropertyChangedCallback callback) {
if (mCallbacks == null) {
mCallbacks = new PropertyChangeRegistry();
}
mCallbacks.add(callback);
}
这样,注册 Observable 对象的监听就完毕了。
更新 (重新绑定) Observable 对象
设置或更新 Observable 对象时都会调用 notifyPropertyChanged()
或 notifyChange()
来通知更新,那到底是如何更新的呢?
- 回调过程
public void notifyPropertyChanged(int fieldId) {
// mCallbacks 是 PropertyChangeRegistry对象,在 addOnPropertyChangedCallback 时实例化
// 如果注册了Observable对象监听,那么mCallbacks不为null
if (mCallbacks != null) {
mCallbacks.notifyCallbacks(this, fieldId, null);
}
}
// baseLibrary
private void notifyCallbacks(T sender, int arg, A arg2, int startIndex, int endIndex, long bits) {
long bitMask = 1L;
for(int i = startIndex; i < endIndex; ++i) {
if((bits & bitMask) == 0L) {
// mNotifier 是实例化PropertyChangeRegistry时创建的
// mNotifier 即 CallbackRegistry.NotifierCallback
this.mNotifier.onNotifyCallback(this.mCallbacks.get(i), sender, arg, arg2);
}
bitMask <<= 1;
}
}
// PropertyChangeRegistry.NOTIFIER_CALLBACK
public void onNotifyCallback(Observable.OnPropertyChangedCallback callback, Observable sender,
int arg, Void notUsed) {
// callback 是为Observable对象添加的OnPropertyChangedCallback,即WeakPropertyListener
callback.onPropertyChanged(sender, arg);
}
// WeakPropertyListener
public void onPropertyChanged(Observable sender, int propertyId) {
// binder 即生成的Binding类对象
ViewDataBinding binder = mListener.getBinder();
...
binder.handleFieldChange(mListener.mLocalFieldId, sender, propertyId);
}
private void handleFieldChange(int mLocalFieldId, Object object, int fieldId) {
// onFieldChange 实现在生成的Binding类中
boolean result = onFieldChange(mLocalFieldId, object, fieldId);
if (result) {
// 如果对象属性变化,将重新绑定
requestRebind();
}
}
通过 notifyPropertyChanged 调用到 mNotifier 回调, mNotifier 通知 OnPropertyChangedCallback
Observable 对象属性发生变化,然后在 onPropertyChanged
中又转给 ViewDataBinding 对象 (生成的 Binding 类) 处理。
- 判断是否需要重新绑定并执行,在生成的 Binding 类中实现
// 生成的Binding类中得方法
protected boolean onFieldChange(int localFieldId, Object object, int fieldId) {
// 如果变量不是Observable类型或没有添加 Bindable注解,就不会判断,直接返回false
switch (localFieldId) {
case 0 :
return onChangeContact((com.connorlin.databinding.model.ObservableContact) object, fieldId);
}
return false;
}
private boolean onChangeContact(com.connorlin.databinding.model.ObservableContact contact, int fieldId) {
switch (fieldId) {
case BR.name: {
synchronized(this) {
mDirtyFlags |= 0x4L;// 通过mDirtyFlags判断对象是否变化
}
return true;
}
...
}
return false;
}
至此,更新过程完毕。
整个注册与更新过程可以用一张流程图来概括:
事件处理
事件处理的原理很简单,在生成 Binding 类中会实现 View 事件的监听,在构造时实例化 View 的事件监听,然后在绑定时将事件监听对象赋值给对应 View,这样,点击时就会触发相应的监听。
这里以 DataBindingDemo 中 EventActivity
部分为例:
- 生成的 Binding 类并实现 View 的事件监听
public class ActivityEventBinding extends android.databinding.ViewDataBinding
implements android.databinding.generated.callback.OnCheckedChangeListener.Listener,
android.databinding.generated.callback.OnClickListener.Listener {
// Checkbox check监听
private final android.widget.CompoundButton.OnCheckedChangeListener mCallback3;
private final android.view.View.OnClickListener mCallback2;
private final android.view.View.OnClickListener mCallback1;
// listeners
private OnClickListenerImpl mAndroidViewViewOnCl;
...
// Listener Stub Implementations
public static class OnClickListenerImpl implements android.view.View.OnClickListener{
private com.connorlin.databinding.handler.EventHandler value;
public OnClickListenerImpl setValue(com.connorlin.databinding.handler.EventHandler value) {
this.value = value;
return value == null ? null : this;
}
@Override
public void onClick(android.view.View arg0) {
this.value.onClickFriend(arg0);
}
}
...
}
- 实例化 View 的事件监听
public ActivityEventBinding(android.databinding.DataBindingComponent bindingComponent, View root) {
super(bindingComponent, root, 0);
...
// listeners
mCallback3 = new android.databinding.generated.callback.OnCheckedChangeListener(this, 3);
mCallback2 = new android.databinding.generated.callback.OnClickListener(this, 2);
mCallback1 = new android.databinding.generated.callback.OnClickListener(this, 1);
invalidateAll();
}
- 在执行绑定中绑定 View 事件监听
@Override
protected void executeBindings() {
...
if ((dirtyFlags & 0x6L) != 0) {
if (handler != null) {
// read handler::onClickFriend
androidViewViewOnCli = (((mAndroidViewViewOnCl == null)
? (mAndroidViewViewOnCl = new OnClickListenerImpl()) : mAndroidViewViewOnCl).setValue(handler));
}
}
// batch finished
if ((dirtyFlags & 0x6L) != 0) {
this.mboundView1.setOnClickListener(androidViewViewOnCli);
}
if ((dirtyFlags & 0x4L) != 0) {
this.mboundView2.setOnClickListener(mCallback1);
this.mboundView3.setOnClickListener(mCallback2);
android.databinding.adapters.CompoundButtonBindingAdapter.setListeners(
this.mboundView4, mCallback3, (android.databinding.InverseBindingListener)null);
}
}
- 触发事件并执行
ViewStub
原理类似,只是利用 ViewStubProxy
来延迟绑定。
- 使用 layout 中的 ViewStub 实例化一个 ViewStubProxy 对象赋给 viewstub 变量,并与 Bingding 关联
public ActivityViewStubBinding(android.databinding.DataBindingComponent bindingComponent, View root) {
super(bindingComponent, root, 0);
final Object[] bindings = mapBindings(bindingComponent, root, 2, sIncludes, sViewsWithIds);
...
this.viewStub = new android.databinding.ViewStubProxy((android.view.ViewStub) bindings[1]);
this.viewStub.setContainingBinding(this);
...
}
- 实例化 ViewStubProxy 的同时会注册 inflate 监听
private OnInflateListener mProxyListener = new OnInflateListener() {
@Override
public void onInflate(ViewStub stub, View inflated) {
mRoot = inflated;
mViewDataBinding = DataBindingUtil.bind(mContainingBinding.mBindingComponent,
inflated, stub.getLayoutResource());
mViewStub = null;
if (mOnInflateListener != null) {
mOnInflateListener.onInflate(stub, inflated);
mOnInflateListener = null;
}
mContainingBinding.invalidateAll();
mContainingBinding.forceExecuteBindings();
}
};
public ViewStubProxy(ViewStub viewStub) {
mViewStub = viewStub;
mViewStub.setOnInflateListener(mProxyListener);
}
- inflate ViewStub
if (!mActivityViewStubBinding.viewStub.isInflated()) {
mActivityViewStubBinding.viewStub.getViewStub().inflate();
}
当 ViewStub infate 时,执行 mProxyListener
,其中会生成 ViewStub 的 Binding,并强制执行主 Binding 重绑
- 绑定 ViewStub
@Override
protected void executeBindings() {
long dirtyFlags = 0;
synchronized(this) {
dirtyFlags = mDirtyFlags;
mDirtyFlags = 0;
}
// batch finished
if (viewStub.getBinding() != null) {
viewStub.getBinding().executePendingBindings();
}
}
这样,ViewStub 绑定就结束了。
本篇完,敬请期待下篇...
我的简书账号是 ConnorLin,欢迎关注!
我的简书专题是 Android 开发技术分享,欢迎关注!
我的个人博客 欢迎关注!
原创文章,欢迎转载,转载请注明出处!
欢迎您扫一扫上面的微信公众号,订阅我的博客!
Android jetpack 之 LiveData
首先,LiveData是什么
LiveData是一种可以被观察的数据存储器类,它可以感知其他组件(比如Activity,Fragment)的生命周期,并只更新处于活跃状态的组件. 当我们的应用组件处于 STARTED 或 RESUMED 状态,LiveData则会认为该组件处于活跃状态
开始使用LiveData,LiveData一般搭配viewmodel一起使用
首先我们会创建一个viewmodel,在viewmodel里面在创建LiveData,并提供getter方法进行访问.
class Nameviewmodel : viewmodel() {
//LiveData是一个抽象类,一般使用它的 mutablelivedata 实现
val currentName: mutablelivedata<String> by lazy {
mutablelivedata<String>()
}
}
接着在Activity的onCreate()方法中获取我们的Numviewmodel (在依赖了Android KTX 中的 Fragment KTX模块后, 可以直接使用viewmodels和activityviewmodels属性委托绑定到viewmodel),接着为LiveDta注册观察者
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
//获取viewmodel对象
val model = viewmodelProvider(this,
viewmodelProvider.NewInstanceFactory()).get(Nameviewmodel::class.java)
//创建观察者对象
val nameObserver = Observer<String> { name ->
//更新UI
}
//通过observe()来注册观察者
model.currentName.observe(this, nameObserver)
}
在注册观察者之后系统会立即调用onChange()方法,来提供currentName中的最新值,如果LiveData对象尚未在currentName中设置值,则onChange()方法不会被调用.
现在已经创建了LiveData对象并且设置了观察者.我们只需要更新LiveData对象就可以完成对onChange()方法的调用.LiveData提了 setValue(T) 和 postValue(T) 两个方法来更新值,第一个用来在主线程上使用,第二个用来在工作线程上使用.
button.setonClickListener {
model.currentName.setValue("乌鸡哥")
}
LiveData 是怎么工作的
首先我们看下LiveData是如何注册一个观察者的
@MainThread
public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) {
//该方法一定要在主线程上调用
assertMainThread("observe");
if (owner.getLifecycle().getCurrentState() == DESTROYED) {
// ignore
return;
}
LifecycleBoundobserver wrapper = new LifecycleBoundobserver(owner, observer);
ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper);
if (existing != null && !existing.isAttachedTo(owner)) {
throw new IllegalArgumentException("Cannot add the same observer"
+ " with different lifecycles");
}
if (existing != null) {
return;
}
owner.getLifecycle().addobserver(wrapper);
}
observe()方法的第一个参数是一个接口,提供了一个获取Lifecycle的方法,该对象可以对我们应用组件(如Activity,Fragment)的生命周期进行监听.LiveData能感知组件生命周期的能力就它带来的. 第二个参数就是我们的观察者对象.
从上面的代码可以看出.如果该观察者所在的组件已经销毁,则什么也不会做.
紧接着,把我们传入的owner 和 observer 做了一个包装. 这个包装类实现了GenericLifecycleObserver这个接口.
然后把我们的观察者都存储到mObservers这个SafeIterableMap里.在这里做了一个判断,即一个观察者只能观察一个LiveData对象.
最后把我们的包装类和Lifecycle做了关联,这时我们的LiveData就获得了应用组件的生命周期感知能力.
那这个包装类是什么
class LifecycleBoundobserver extends ObserverWrapper implements GenericLifecycleObserver {
@NonNull
final LifecycleOwner mOwner;
LifecycleBoundobserver(@NonNull LifecycleOwner owner, Observer<? super T> observer) {
super(observer);
mOwner = owner;
}
//判断该组件是否是活跃状态,大于等于STARTED时返回true
@Override
boolean shouldBeActive() {
return mOwner.getLifecycle().getCurrentState().isAtLeast(STARTED);
}
//当组件的生命周期发生改变时调用
@Override
public void onStateChanged(LifecycleOwner source, Lifecycle.Event event) {
if (mOwner.getLifecycle().getCurrentState() == DESTROYED) {
removeObserver(mObserver);
return;
}
activeStateChanged(shouldBeActive());
}
@Override
boolean isAttachedTo(LifecycleOwner owner) {
return mOwner == owner;
}
@Override
void detachObserver() {
mOwner.getLifecycle().removeObserver(this);
}
}
.当观察者所在的组件生命周期发生改变后,会回调onStartChange,在里面会首先检查组件是不是已经销毁,销毁的话需要移除LiveData的观察者,还要移除包装类和Lifecycle的关联.
@MainThread
public void removeObserver(@NonNull final Observer<? super T> observer) {
assertMainThread("removeObserver");
ObserverWrapper removed = mObservers.remove(observer);
if (removed == null) {
return;
}
removed.detachObserver();
removed.activeStateChanged(false);
}
在里面首先会从mObservers这个SafeIterableMap里面移除LiveData的观察者. 接着调用detachObserver移除包装类和Lifecycle的关联.最后调用activeStateChanged(false)
如果组件没有销毁,则会直接调用activeStateChanged(shouldBeActive())
void activeStateChanged(boolean newActive) {
//如果状态没改变,什么也不做
if (newActive == mActive) {
return;
}
// immediately set active state, so we'd never dispatch anything to inactive
// owner
//更新状态
mActive = newActive;
//当前LiveData没有任何活跃的观察者时为true
boolean wasInactive = LiveData.this.mActiveCount == 0;
LiveData.this.mActiveCount += mActive ? 1 : -1;
if (wasInactive && mActive) {
onActive();
}
if (LiveData.this.mActiveCount == 0 && !mActive) {
onInactive();
}
if (mActive) {
dispatchingValue(this);
}
}
在里面就是判断了一下LiveData里面是否还有活跃的观察者.,从上面的代码看到,只有LiveData里面的活跃观察者从0变成1的时候才会调用onActive,并且只有活跃的观察者变成0的时候才会调用onInactive.最后判断了一个这个观察者是否是活跃的,如果是活跃的会调用dispatchingValue来向这一个观察者发送事件.
使用setValue来通知观察者更新数据
@MainThread
protected void setValue(T value) {
assertMainThread("setValue");
mVersion++;
mData = value;
dispatchingValue(null);
}
void dispatchingValue(@Nullable ObserverWrapper initiator) {
//首先会判断是不是在分发事件,如果正在分发事件,则什么也不做
if (mdispatchingValue) {
mdispatchInvalidated = true;
return;
}
mdispatchingValue = true;
do {
mdispatchInvalidated = false;
if (initiator != null) {
considerNotify(initiator);
initiator = null;
} else {
//通知所有的观察者
for (Iterator<Map.Entry<Observer<? super T>, ObserverWrapper>> iterator =
mObservers.iteratorWithAdditions(); iterator.hasNext(); ) {
considerNotify(iterator.next().getValue());
if (mdispatchInvalidated) {
break;
}
}
}
} while (mdispatchInvalidated);
mdispatchingValue = false;
}
private void considerNotify(ObserverWrapper observer) {
//观察者不是活跃的,什么也不做
if (!observer.mActive) {
return;
}
...
if (!observer.shouldBeActive()) {
observer.activeStateChanged(false);
return;
}
if (observer.mLastVersion >= mVersion) {
return;
}
observer.mLastVersion = mVersion;
//noinspection unchecked
observer.mObserver.onChanged((T) mData);
}
在观察者调用onChanged方法之前,仍会有很多的判断.比如检查观察者是不是活跃的.是不是已经通知过了. 我们的LiveData里又一个mVersion.这个mVersion在每次的setValue操作后都会自增. 而我们的ObserverWapper 也会有一个mLastVersion.比较这两个值就可以确定我们的观察者是否已经回调了onChanged.
LiveData还有一个observeForever方法.只需传递一个观察者对象就好.使用这个方法来注册观察者会是LiveData失去生命周期感知能力.我们需要自己在合适的生命周期回调方法中移除观察者
扩展LiveData
我们可以扩展一个LiveData来监听一些服务
class MoneyLiveData : LiveData<BigDecimal>(){
//金钱的管理类
private val manager = MoneyManager()
private val listener = { money: BigDecimal ->
value = money
}
override fun onActive() {
super.onActive()
manager.registerListener(listener)
}
override fun onInactive() {
super.onInactive()
manager.removeListener(listener)
}
}
这里包含一些重要的方法,onActive() 会在有活跃的观察者时调用, onInactive() 会在没有任何活跃的观察者时调用. setValue(T)会更新LiveData实例的值并将结果告知所有活跃的观察者,可以在Activity的onCreate()方法中使用
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val moneyLiveData: MoneyLiveData = ...
moneyLiveData.observe(this, Observer<BigDecimal> { money ->
//更新UI
})
}
转换LiveData
有时候我们会希望将LiveData对象分派给观察者之前改变里面存储的值,map(),又或者转换成别的LiveData对象,switchMap()
val oldLiveData: LiveData<String> = OldLiveData()
//使用 Transformations 的map() 来在对前一个LiveData的值进行修改
val newLiveData: LiveData<String> = Transformations.map(oldLiveData) {
oldString -> "newString"
}
newLiveData.observe(this, Observer { Log.d("TAG", it)})
val oldLiveData: LiveData<String> = mutablelivedata<String>()
val newLiveData: LiveData<String> = mutablelivedata<String>()
//使用 Transformations 的switchMap()来对前一个LiveData转换为一个新的LiveData
val liveData = Transformations.switchMap(oldLiveData) { newLiveData}
liveData.observe(this, Observer { Log.d("TAG", it)})
我们今天的关于android-从LiveData.observe()向适配器添加项目的最佳实践和android recyclerview适配器的分享已经告一段落,感谢您的关注,如果您想了解更多关于android -------- LiveDataBus的使用、Android BaseAdapter DataSetObserver通知机制、Android Data Binding 系列 (二) -- Binding 与 Observer 实现原理、Android jetpack 之 LiveData的相关信息,请在本站查询。
本文标签: