LiveData的使用
简介:
- 介绍:LiveData是一种可观察的数据存储器类;比较鲜明的特征就是LIveData具有生命周期的感知能力,能够响应组件(活动服务碎片等)生命周期,以确保LiveData仅更新处于活跃生命周期状态下的组件观察者;
livedata是数据容器->livedata默认实现了观察者模式->数据是被观察的->当数据发生变化->通知观察者;
- 总结:
- 是一个类,是一个储存信息的类,可以观察;
- 可以感知组件的生命周期;
- 更新处于活跃状态下的生命周期;
- 那么问题来了,什么可以被称之位活跃状态?
观察者的组件的生命周期位于Started或Resumed状态;
- 活动或者是碎片能再生命周期结束的时候立刻解除对数据的订阅,当组件的状态变化destroyded 时->观察者 LifecycleObserver 组件的状态也变为 Destroyed ->系统会自动移除观察者;
- 当我们更新livedata中的值时,会触发所有注册这个livedata的观察者(处于活跃状态的);
优势:
- 自动更新界面数据:遵循观察者模式,当数据发生改变时,livedata会通知Observer对象, 观察者会替你进行更新;
- 不会因为活动的停止就崩溃,因为当组件变为非活跃状态时,只会不接受livedata事件 ;而且不需要手动处理生命周期,livedata会自动管理这些事件 ,做出响应->比如当旋转屏幕/由不可见变得可见时->会接受最新的数据;
- 如果livedata是单例的话,可以分享数据;
LiveData的使用:
- 在viewmodel中:创建一个livedata实例,储存数据;
- 在活动/碎片中:创建observer的实例,通过onchanged方法,响应liveData数据的变化;
- 在活动/碎片中:将两者相关联,通过Livedata的observer方法;
还有一个方法:
- 使用obServeForever(Observer)的方式来注册观察者;
- 通过removeObserver(Observer) 来移除观察者;
这种情况下,观察者始终会被认为是活跃的状态,始终都会接受到livedata的通知;
所以一定要记得移除啊,否则一直都会订阅,Livedata一直处于激活状态,导致活动不会被系统回收,造成了内存泄漏;
创建livedata的对象
livedata可以承载任何数据的容器,通常用于viewModel对象中,并且通过getter方法进行访问;
livedata是抽象类,我们通常使用MutableLiveData,是livedata的子类;
Java
public class BookViewModel extends ViewModel {
private MutableLiveData<Book> mutableLiveData;
public MutableLiveData<Book> getBook(){
if(mutableLiveData == null){
mutableLiveData = new MutableLiveData<>();
}
return mutableLiveData;
}
}
为什么不放在活动/碎片中?
- 活动/碎片中,你应该去做UI的更新,不能储存数据喔!!!
- 不随着活动/碎片生命周期,这样在配置更改之后livedata才能继续保存啊
观察livedata对象
在活动/碎片中的oncreate方法中开始观察livedata:
- 确保活动/碎片变为活跃状态之前具有可以显示的数据;当处于活跃状态时,会从正在观察的livedata对象中获取最新值;
- onresume会多次调用;
如果观察者从第二次非活跃变为活跃时,只有在上次变为活跃状态以来值发生变化,才会更新;
Java
Book book1 = new Book("ll","jj");
binding.setBookin(book1);
//获得viewmodel对象
BookViewModel bookViewModel = new ViewModelProvider(this).get(BookViewModel.class);
//创建观察者
final Observer<Book> observer = new Observer<Book>() {
@Override
public void onChanged(Book book) {
//更新UI
binding.setBookin(book);
}
};
//观察这个livedata,使得活动作为lifecycleowner
bookViewModel.getBook().observe(this,observer);
调用observe之后,如果给livedata设置值了,会调用Onchanged方法,否则不会;
观察者的两种方式:
方式一:
Java
//创建观察者
final Observer<Book> observer = new Observer<Book>() {
@Override
public void onChanged(Book book) {
//更新UI
binding.setBookin(book);
}
};
//观察这个livedata,使得活动作为lifecycleowner
bookViewModel.getBook().observe(this,observer);
就是new一个观察者,通过Livedata的Obsetve方法
方式二:
结合databinding:
databinding.setLifecycleOwner(this);
修改值
livedata没有公开可用的方法来更新存储的数据,MutableLiveData setvalue(T)(修改值),postvalue(T)可以修改livedata对象中的值,所以通常会使用MutableLiveData;
- setvalue(T):必须用在主线程;
- postvalue(T):任意线程都可以使用,底层会使用:handler.post;
Java
binding.bt.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
bookViewModel.getBook().setValue(new Book("ljxxhswy","swyxhljx"));
}
});
源码分析:
liveData的重要方法有两个,所以我们着重讲:observe方法和setvalue方法
observe
Java
@MainThread
public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<T> observer) {
//判断是否被销毁
if (owner.getLifecycle().getCurrentState() == DESTROYED) {
return;
}
//利用LifecycleBoundObserver包装起来
LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer);
//如果有缓存,直接从缓存中读取observe
ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper);
//如果添加过,缓存的observe和owner的observe不一致会报错
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方法小结:
- 判断是不是被销毁,如果销毁直接返回;
- 包装;
- 判断是不是被添加过,如果被添加过直接返回;
- 如果没有被添加过,把包装后的添加进去;
当生命周期变化时,会先通知LifecycleBoundObserver的onStateChanged 方法,让这个方法又会回调observer 的 onChange 方法;
所以先来看看onStateChanged
Java
class LifecycleBoundObserver extends ObserverWrapper implements GenericLifecycleObserver {
@NonNull final LifecycleOwner mOwner;
LifecycleBoundObserver(@NonNull LifecycleOwner owner, Observer<T> observer) {
super(observer);
mOwner = owner;
}
@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());
}
}
- 生命周期变化时,如果destory了,会直接移除观察者,这也是为什么不需要我们去手动移除观察着的原因;
- activeStateChanged(shouldBeActive());当lifecycle的state是激活状态时,shouldBeActive()的方法返回值是true;
activeStateChanged(shouldBeActive()):
Java
void activeStateChanged(boolean newActive) {
//如果和上一次状态一致,直接返回
if (newActive == mActive) {
return;
}
// immediately set active state, so we'd never dispatch anything to inactive
// owner
mActive = newActive;
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);
}
}
里面有三个变量:
- mActive:记录当前的状态;
- wasInactive :记录之前有没有激活状态;
- mActiveCount:记录激活状态的总数;
里面有三个方法:
- onActive():所以它是当前是激活状态,而且之前没有激活状态的observe回调,适合做一些后台的开始工作;
- onInactive():当最后一个观察者变为非活跃的时候调用,适合做停止后台工作;
- dispatchingValue(this):当当前是活跃状态时会回调;
当当前是激活状态,会触发:dispatchingValue(this);
Java
private void dispatchingValue(@Nullable ObserverWrapper initiator) {
//如果正在处理返回
if (mDispatchingValue) {
mDispatchInvalidated = true;
return;
}
mDispatchingValue = true;
do {
mDispatchInvalidated = false;
if (initiator != null) {
considerNotify(initiator);
initiator = null;
} else {
//如果initiator为null,会遍历所有的Observe,分发;
for (Iterator<Map.Entry<Observer<T>, ObserverWrapper>> iterator =
mObservers.iteratorWithAdditions(); iterator.hasNext(); ) {
considerNotify(iterator.next().getValue());
if (mDispatchInvalidated) {
break;
}
}
}
} while (mDispatchInvalidated);
mDispatchingValue = false;
}
considerNotify 方法:
Java
private void considerNotify(ObserverWrapper observer) {
// 如果状态不是在活跃中,直接返回,所以不会回调Onchange方法,不会更新数据的原因;
if (!observer.mActive) {
return;
}
// Check latest state b4 dispatch. Maybe it changed state but we didn't get the event yet.
//
// we still first check observer.active to keep it as the entrance for events. So even if
// the observer moved to an active state, if we've not received that event, we better not
// notify for a more predictable notification order.
if (!observer.shouldBeActive()) {
observer.activeStateChanged(false);
return;
}
//如果数据最新,返回
if (observer.mLastVersion >= mVersion) {
return;
}
//更新版本号
observer.mLastVersion = mVersion;
//noinspection unchecked
// 调用外部的 mObserver 的 onChange 方法
observer.mObserver.onChanged((T) mData);
}
setValue
Java
@MainThread
protected void setValue(T value) {
assertMainThread("setValue");
mVersion++;
mData = value;
dispatchingValue(null);
}
- 会加一个版本号,然后设置值;
- 有一个巧妙构思,如果当前状态是destory的话,会版本号+1,然后由于处于destory状态dispatchingValue(null)会直接返回;当回到前台的时候,此时生命周期的变化会触发onstatechange回调,最后还是会触发dispatchingValue(null),此时版本号不一致,会更新数据;这也就是为什么重新回到前台会更新的原因;
postValue
Java
protected void postValue(T value) {
boolean postTask;
//判断有没有任务在执行;
synchronized (mDataLock) {
postTask = mPendingData == NOT_SET;
mPendingData = value;
}
//如果有任务直接返回
if (!postTask) {
return;
}
AppToolkitTaskExecutor.getInstance().postToMainThread(mPostValueRunnable);
}
private final Runnable mPostValueRunnable = new Runnable() {
@Override
public void run() {
Object newValue;
synchronized (mDataLock) {
newValue = mPendingData;
//会更新执行的任务
mPendingData = NOT_SET;
}
setValue((T) newValue);
}
}
- 从上述代码中,我们可以看到使用了同步锁,这是因为postvalue在子线程中,如果不加锁,会出现很多问题;
- 然后使用postTask标记是否有线程在执行任务;
- 最后调用AppToolkitTaskExecutor.getInstance().postToMainThread(mPostValueRunnable);会到主线程去更新UI;
observeForever
Java
@MainThread
public void observeForever(@NonNull Observer<T> observer) {
AlwaysActiveObserver wrapper = new AlwaysActiveObserver(observer);
ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper);
if (existing != null && existing instanceof LiveData.LifecycleBoundObserver) {
throw new IllegalArgumentException("Cannot add the same observer"
+ " with different lifecycles");
}
if (existing != null) {
return;
}
wrapper.activeStateChanged(true);
}
private class AlwaysActiveObserver extends ObserverWrapper {
AlwaysActiveObserver(Observer<T> observer) {
super(observer);
}
@Override
boolean shouldBeActive() {
return true;
}
}
AlwaysActiveObserver这个类没有实现GenericLifecycleObserver 方法接口;
实现GenericLifecycleObserver接口->生命周期变化时,会回调 onStateChange ->没有实现->生命周期变化不会通知->所以不会主动removeobserve方法;
本次分享到此结束,谢谢大家!