Android-Jetpack笔记-LiveData

483 阅读2分钟

LiveData即有生命的数据,通过观察者模式实现,当数据发生变化时可以收到回调。同时还具备感知宿主生命周期的能力。

Jetpack笔记代码

本文源码基于SDK 29

使用

引入依赖:

def lifecycle_version = "2.2.0"
//extensions包含Lifecycles、LiveData、ViewModel
implementation "android.arch.lifecycle:extensions:$lifecycle_version"

在act中使用,

class ViewModelActivity extends BaseActivity {
    MutableLiveData<String> mLiveData = new MutableLiveData<>();

    void onCreate(Bundle savedInstanceState) {
        //观察数据变化
        mLiveData.observe(this, s -> {
            QrLog.e("observe = " + s + "," + getLifecycle().getCurrentState());
        });
        //设置数据
        mLiveData.setValue("onCreate");
    }

    void onResume() {
        //设置数据
        mLiveData.setValue("onResume");
    }
}

使用起来很简单,下面来看看是怎么实现的。

原理

首先看mLiveData.observe

//LiveData.java
public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) {
    //owner是act对象,在Lifecycles中提到过,他可以作为一个被观察者
    //observer是观察者
    if (owner.getLifecycle().getCurrentState() == DESTROYED) {
        return;
    }
    //包装被观察者和观察者
    LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer);
    //存储起来,<观察者,包装类>
    ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper);
    //包装类成为act的观察者,能感知act生命周期
    owner.getLifecycle().addObserver(wrapper);
}

来到setValue

//LiveData.java
protected void setValue(T value) {
    //把值记录起来
    mData = value;
    //开始分发
    dispatchingValue(null);
}

void dispatchingValue(@Nullable ObserverWrapper initiator) {
    do {
        for (Iterator<Map.Entry<Observer<? super T>, ObserverWrapper>> iterator =
             mObservers.iteratorWithAdditions(); iterator.hasNext(); ) {
            //遍历包装类
            considerNotify(iterator.next().getValue());
            if (mDispatchInvalidated) {
                break;
            }
        }
    } while (mDispatchInvalidated);
}

private void considerNotify(ObserverWrapper observer) {
    //从包装类中取出观察者,回调
    observer.mObserver.onChanged((T) mData);
}

到这里,流程就已经走完了,值得注意的是,并不是所有生命周期都能观察到值的变化,试着在每个生命周期都setValue一下,会发现只有onStart、onResume、onPause才会收到回调,这是因为,

//LiveData.java
private void considerNotify(ObserverWrapper observer) {
    if (!observer.shouldBeActive()) {
        //判断是否活跃
        observer.activeStateChanged(false);
        return;
    }
    //从包装类中取出观察者,回调
    observer.mObserver.onChanged((T) mData);
}

shouldBeActive有两个实现,我们先看这个,

//LiveData.LifecycleBoundObserver
@Override
boolean shouldBeActive() {
    //只有getLifecycle().getCurrentState()大于等于STARTED,才通知
    return mOwner.getLifecycle().getCurrentState().isAtLeast(STARTED);
}

看下日志,可见只有onStart、onResume、onPause时,getLifecycle().getCurrentState()大于等于STARTED,

再看下另一个实现,

//LiveData.AlwaysActiveObserver
@Override
boolean shouldBeActive() {
    //直接返回true
    return true;
}

当调用observeForever时,创建的包装类就是AlwaysActiveObserver,所以,这时可以在所有生命周期都收到通知,

当然,调用observeForever的话,由于他的包装类没有进行removeObserver,需要在业务层手动移除,否则可能会造成内存泄漏,

  • observe:包装类是LifecycleBoundObserver(有活跃边界),内部会调removeObserver
  • observeForever:包装类是AlwaysActiveObserver (总是活跃),需要手动调removeObserver

优缺点

  • 优点:
    • 使用简单,可以避免内存泄漏,RxJava则需结合RxLifecycle
    • 能感知生命周期,在页面活跃状态才进行通知,可以避免页面不可见时还在占资源

参考文章

本文使用 mdnice 排版