一、介绍
1、LiveData
LiveData是一种可调查的数据存储器类。与常规的可调查类不同,LiveData具有生命周期感知才能,意指它遵循其他运用组件(如Activity
、Fragment
或Service
的生命周期。这种感知才能可保证LiveData仅更新处于活泼生命周期状况的运用组件调查者。 假如调查者(由Observer
类表明)的生命周期处于STARTED
或RESUMED
状况,则LiveData会认为该调查者处于活泼状况。LiveData只会将更新告诉给活泼的调查者。为调查LiveData目标而注册的非活泼调查者不会收到更改告诉。
2、ViewModel
ViewModel 类旨在以注重生命周期的办法存储和管理界面相关的数据。首要作用是对数据状况的持有和维护。能够用来解决以下两个问题:
-
Activity装备更改重建时(比方屏幕旋转)保留数据
-
UI组件(Activity与Fragment、Fragment与Fragment)间完成数据共享
ViewModel通常与LiveData这个数据驱动器结合在一起运用。将用于更新界面的 LiveData
目标存储在 ViewModel
目标中,而不是将其存储在 Activity 或 Fragment 中,原因如下:
-
避免 Activity 和 Fragment 过于庞大。界面控制器只负责显示数据,不负责存储数据状况。
-
将
LiveData
实例与特定的 Activity 或 Fragment 实例分脱离。这样LiveData
目标在装备更改后能够持续存在。
LiveData供给感知lifecycle生命周期的数据告诉才能,viewModel作为存储LiveData避免被宿主毁掉的容器。
二、基本运用
1、LiveData运用
1)创立LiveData目标
MutableLiveData<String> liveData = new MutableLiveData<>();
2)调查LiveData目标
经过observe
办法来监听LiveData
的数据变化,每当LiveData
产生变化时,都会回调onChanged
办法,并返回值的内容
liveData.observe(this, new Observer<String>() { @Override public void onChanged(String s) { //更新UI }});
3)更新LiveData目标
经过LiveData
的setValue
办法,给LiveData
赋值,每次赋完值后,都会回调onChanged
办法。假如是在异脚步线程中更新数据,在主线程更新监听,则需要调用postValue办法。
liveData.postValue("a");liveData.setValue("b");
2、结合ViewModel运用
1)在ViewModel中存储LiveData目标
public class PtListViewModel extends ViewModel {private final MutableLiveData<List<SupposeItem>> supposeListLiveData = new MutableLiveData<>(); public MutableLiveData<List<SupposeItem>> getSupposeListLiveData() { return supposeListLiveData; } public void setSupposeList(List<SupposeItem> list){ supposeListLiveData.setValue(list); }}
2)在Activity的onCrete阶段调查LiveData
final PtListViewModel mViewModel = new ViewModelProvider(mContext).get(PtListViewModel.class); mViewModel.getSupposeListLiveData().observe(mContext, supposeItems -> ());
每当有值产生变化时,就会收到最新值的告诉。一旦运用组件处于 STARTED
状况,就会从它正在调查的 LiveData
目标接纳最新值
3)更新LiveData值
能够结合网络请求或许需要在不同Fragment之间传递某些状况/筛选值时,经过setValue或postValue传值
new ViewModelProvider(JobInfoListFragmentActivity.this).get(PtListViewModel.class).setSupposeList(bean.data);
三、原理解析
1、注册监听observer()
@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); }
调用observer()
时,传递了两个参数,第一个是LifecycleOwner
接口实例,第二个参数Observer
就是咱们调查的回调。接下来将这两个参数传递new出了一个新的目标:LifecycleBoundObserver
,最后将LifecycleBoundObserver
和LifecycleOwner
进行了绑定。
2、LifecycleBoundObserver
class LifecycleBoundObserver extends ObserverWrapper implements GenericLifecycleObserver { @NonNull final LifecycleOwner mOwner; LifecycleBoundObserver(@NonNull LifecycleOwner owner, Observer<? super T> observer) { super(observer); mOwner = owner; } @Override boolean shouldBeActive() { return mOwner.getLifecycle().getCurrentState().isAtLeast(STARTED); } //Activity生命周期变化时,回调办法 @Override public void onStateChanged(LifecycleOwner source, Lifecycle.Event event) {
//destroy状况解绑,能够避免内存走漏
if (mOwner.getLifecycle().getCurrentState() == DESTROYED) { removeObserver(mObserver); return; } //只要是Active状况才会去更新livedata activeStateChanged(shouldBeActive()); } @Override boolean isAttachedTo(LifecycleOwner owner) { return mOwner == owner; } //解除监听 @Override void detachObserver() { mOwner.getLifecycle().removeObserver(this); } }
能够看到这里面与LifecycleOwner
进行了绑定,而且完成了onStateChanged
办法,当生命周期产生变化时执行activeStateChanged(shouldBeActive());
办法;shouldBeActive()
返回了 要求生命周期至少是STARTED状况才被认为是activie状况;假如state是DESTROYED
状况时,则移除调查者,在 Activity、Fragment的生命周期走到 onDestroy 的时候,就会取消订阅,避免内存走漏。
3、dispatchingValue()
持续追寻activeStateChanged
办法发现,在里面做了一些活泼状况值的操作,而且当状况活泼时,更新数据值。
void activeStateChanged(boolean newActive) { if (newActive == mActive) { return; } // immediately set active state, so we\'d never dispatch anything to inactive // owner mActive = newActive;.... if (mActive) { dispatchingValue(this); } }
void dispatchingValue(@Nullable ObserverWrapper initiator) { ... //遍历LiveData的一切调查者执行下面代码 for (Iterator<Map.Entry<Observer<? super T>, ObserverWrapper>> iterator = mObservers.iteratorWithAdditions(); iterator.hasNext(); ) { considerNotify(iterator.next().getValue()); if (mDispatchInvalidated) { break; } } ...}//将数据值回调到livedata.observer()回去private void considerNotify(ObserverWrapper observer) { if (!observer.mActive) { return; } if (!observer.shouldBeActive()) { observer.activeStateChanged(false); return; } if (observer.mLastVersion >= mVersion) { return; } observer.mLastVersion = mVersion; observer.mObserver.onChanged((T) mData); }
能够看到当状况从不活泼到活泼状况,产生状况改变时。会遍历一切注册的调查者,判别数据version<=最新数据version(数据产生变化),就会调用调查者的onChanged来告诉数据产生变化。
4、用户主动调用setValue()/postValue()
@MainThread protected void setValue(T value) { assertMainThread("setValue"); mVersion++; mData = value; dispatchingValue(null); }
private final Runnable mPostValueRunnable = new Runnable() { @SuppressWarnings("unchecked") @Override public void run() { Object newValue; synchronized (mDataLock) { newValue = mPendingData; mPendingData = NOT_SET; } setValue((T) newValue); } };
postValue()
在子线程更新数据,经过Hander做了线程切换,终究调用setValue办法。而setValue中就是调用了上面剖析的 dispatchingValue告诉调查者。
5、LiveData 的observeForever办法
这个办法比observe办法少一个LifecycleOwner参数,为啥呢?因为这个办法不需要感知生命周期,需要在setValue 值更新时立马收到回调。
6、LiveData的数据倒灌问题
倒灌现象:
先给LiveData设置了value,然后监听者才开端对LiveData进行监听,这时LiveData的value会立马回调给监听者
原因:
LiveData每次setValue或postValue时mVersion都会自增(见上文setValue源码),当调用LiveData进行observe时,终究会调到如下办法
private void considerNotify(ObserverWrapper observer) { ... if (observer.mLastVersion >= mVersion) { return; } observer.mLastVersion = mVersion; observer.mObserver.onChanged((T) mData); }
当observer的mLastVersion小于mVersion时就会把之前的数据回调给监听者,observer的mLastVersion的初始值为-1
static final int START_VERSION = -1;...int mLastVersion = START_VERSION;
当咱们setValue时,mVersion会从-1开端自增,之后咱们去observe时,因为observer的mLastVersion的初始值是-1,比mVersion=0小,所以调用observe时,会立马把旧的数据回调给调查者。
参考资料:
developer.android.com/topic/libra…
developer.android.com/topic/libra…