在使用一个新的组件之前,我们需要了解为什么需要使用它、如何使用、使用过程中的注意事项、可扩展或可提升的地方。当我们深入透彻理解这些后,开发中遇到任何问题都可以迎刃而解。当然需要了解这些内容,我们必须熟悉源码的实现过程,这样才能做到心中有数。
LiveData 是一种可观察的数据存储器。应用中的其他组件可以使用此存储器监控对象的更改,而无需在它们之间创建明确且严格的依赖路径。LiveData 组件还遵循应用组件(如 Activity、Fragment 和 Service)的生命周期状态,并包括清理逻辑以防止对象泄漏和过多的内存消耗
其实单独使用LiveData没有太大的意义,它只是可观察的数据存储器,当数据发送的变化的时候,通知相应的Obserer,再执行相应的操作,默认观察数据需要在UI线程里面完成。LiveData是Android 架构组件的一部分,所以使用方面来讲就应该和其他的组件一起使用,从而达到解耦以及灵活的目的。这里主要和ViewModel结合使用更能体现其价值。LiveData也有其他可替代的选择,比如项目中使用Rxjava就可以继续使用,也不用进行替换。
observe(LifecycleOwer,Observer)模式,和生命周期自动结合使用。
private MutableLiveData userLiveData = new MutableLiveData<>();
private void initObserver(){
userLiveData.observe(this, new Observer() {
@Override
public void onChanged(@Nullable User user) {
Toast.makeText(getApplicationContext(),user.name,Toast.LENGTH_SHORT).show();
}
});
}
private void changeData(){
User user = new User();
user.name = "test1";
//自动切换到主线程中执行
userLiveData.postValue(user);
//如果能够确定在主线程可以使用该方法
//userLiveData.setValue(user);
}
private static class User {
String name;
}
LiveData的使用还是很简单的,调用observe()方法,然后再数据改变的时候调用postValue()或者setValue()即可,setValue()需要保证调用在UI线程,而postValue()自动切换到UI线程中,其中postValue()也是基于Handler来实现,代码如下:
protected void postValue(T value) {
boolean postTask;
synchronized (mDataLock) {
postTask = mPendingData == NOT_SET;
mPendingData = value;
}
if (!postTask) {
return;
}
ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable);
}
//ArchTaskExecutor使用DefaultTaskExecutor 的postToMainThread()方法
public class DefaultTaskExecutor extends TaskExecutor {
//省略部分代码
......
@Override
public void postToMainThread(Runnable runnable) {
if (mMainHandler == null) {
synchronized (mLock) {
if (mMainHandler == null) {
mMainHandler = new Handler(Looper.getMainLooper());
}
}
}
//noinspection ConstantConditions
mMainHandler.post(runnable);
}
}
LiveData的文档中有这样一段注释:
/**
* LiveData is a data holder class that can be observed within a given lifecycle.
* This means that an {@link Observer} can be added in a pair with a {@link LifecycleOwner}, and
* this observer will be notified about modifications of the wrapped data only if the paired
* LifecycleOwner is in active state. LifecycleOwner is considered as active, if its state is
* {@link Lifecycle.State#STARTED} or {@link Lifecycle.State#RESUMED}.
*
*
.......
*/
意思是如果使用observe()方法,那么会和LifecycleOwner相关,只有在LifecycleOwner的Lifecycle的状态为STARTED或者RESUMED的情况下才会通知更改。如果Activity A 跳转到 Activity B,那么Activit A的Lifecycle的状态变成了CREATED,那么如果此时Activity A的LiveData发生了变化,是不会回调Observer的。举个应用场景,原生个人信息界面 PersonActivity,展现用户的基本信息;开通会员界面,h5界面。如果用户从PersonActivity跳转到开通会员界面,会员开通成功后,需要通知PersonActivity更新,通常我们需要请求一次接口,获取最新用户数据。而我们又是结合LiveData使用,按照上面的注释,PersonActivity是不是就不能回调Observer?答案是的,但是当我们从H5界面回到PersonActivity的时候,会看到数据刷新了,那么文档的解释有误呢?下面我们从源码层了解其实现原理:
1,在LifecycleBoundObserver中监听了LifeCycle的生命周期变化,当生命周期发生变化时,会执行onStateChanged方法。
class LifecycleBoundObserver extends ObserverWrapper implements GenericLifecycleObserver {
.......省略部分.......
@Override
public void onStateChanged(LifecycleOwner source, Lifecycle.Event event) {
if (mOwner.getLifecycle().getCurrentState() == DESTROYED) {
removeObserver(mObserver);
return;
}
activeStateChanged(shouldBeActive());
}
}
//当Activity 的生命周期onResume()执行后,Lifecyle的STATE为RESUMED
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);
}
}
//
private 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, ObserverWrapper>> iterator =
mObservers.iteratorWithAdditions(); iterator.hasNext(); ) {
considerNotify(iterator.next().getValue());
if (mDispatchInvalidated) {
break;
}
}
}
} while (mDispatchInvalidated);
mDispatchingValue = false;
}
//通知更新,只有状态为 active才执行
private void considerNotify(ObserverWrapper observer) {
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
observer.mObserver.onChanged((T) mData);
}
那么为什么要这样设计呢?思考了一下,更主要的目的应该是减少程序的奔溃的发生,如果程序内存不足的情况下,会对后台的资源进行回收,难免会对Activity的资源进行回收,如果我们不加以控制,强制让后台界面做一些更新操作,就会引发空指针异常(像这种问题其实不是特别好定位),导致程序的崩溃,带来不好的用户体验。如果在生命周期的onStart()或者onResume()之后再执行更新操作,就能避免这种空指针的错误。