jetpack系列之Lifedata

目录结构

1.背景及livedata优劣势
2.livedata简单使用
3.livedata实现原理

1.背景及优劣势

1.优势1 感知生命周期UI活跃才刷新UI

比较常见的场景是当网络请求结果回来的时候,经常需要判断 Activity 或者 Fragment 是否已经 Destroy, 如果不是 destroy,才更新 UI

2.防止内存泄漏

livedata是在lifecycle基础上实现,当对应的Lifecycle销毁,会自动解除livedata和被观察者,比如activity的绑定关系,避免内存泄漏

3.防止数据丢失

LiveData在横竖屏切换等Configuration改变时,也能保证获取到最新数据。实现原理我们在后面的文章里面详细说。

2.简单使用

LiveData 是一个抽象类,它的实现子类有 MutableLiveData ,MediatorLiveData。常用的是 MutableLiveData。他常常结合 ViewModel 使用
依赖添加:

implementation "android.arch.lifecycle:livedata:1.1.0"
1.在viewmodle中创建 livedata
public class NameViewModel extends ViewModel {
    private MutableLiveData currentName;
    public MutableLiveData getCurrentName(){
        if(currentName==null){
            currentName=new MutableLiveData<>();
        }
        return currentName;
    }
}
2.在被观察者中建立联系

通过ViewModelProviders 获取到Viewmodel然后调用model中方法调用observe传入被观察者和观察回调 ,当有变化,就会调用到onChanged方法

        //需要一个观察者来观察数据
        Observer observer=new Observer(){
            @Override
            public void onChanged(String s) {
                nameTextView.setText(s);
            }
        };
        //获取到viewmodel
        model= ViewModelProviders.of(this).get(NameViewModel.class);
        //取出livedata完成订阅
        model.getCurrentName().observe(this,observer);

接收事件LiveData提供了两种添加观察者的方法:observeForever()、observe()。使用observeForever()这个还必须手动调用remove方法移除,使用该方法 就不会管被观察者是否处于活跃状态。

3.发送事件

当需要变化,调用viewmodel 的setvalue 或者postvalue放松更新数据 ,比如下面我直接在一个按钮点击事件中,触发。
两者区别:

  • setValue()要在主线程中调用, 实际上是会在调用 serValue 方法的线程回调
  • postValue()既可在主线程也可在子线程中调用。
btn.setOnClickListener(new View.OnClickListener(){
            @Override
            public void onClick(View v) {
                model.getCurrentName().postValue("XXX");
            }
        });

3.源码分析

1.先看livedata类的observe方法

我们在被观察者类中,调用MutableLiveData的observe方法,这个类里面定义了set postValue方法,观察方法还是在Livedata中实现:首先判断是在主线程,否则抛出异常,然后再判断当前被观察的对象状态,如果是DESTROYED状态那么return 然后封装放到一个安全的map中并绑定wrapper作为观察者,最后一行代码,还是调用lifecycle的addobserver(观察者)绑定生命周期观察。

public void observe(@NonNull LifecycleOwner owner, @NonNull Observer 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);
    }
2.绑定后使用setValue与postValue通知观察者

可以看到下面代码最后一行里,还是调用的主线程handler实现切换到主线程,最后调用setValue

protected void postValue(T value) {
        boolean postTask;
        synchronized (mDataLock) {
            postTask = mPendingData == NOT_SET;
            mPendingData = value;
        }
        if (!postTask) {
            return;
        }
        ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable);
    }

3.在setValue方法中调用dispatchingValue

分发value里回调用到considerNotify(initiator)方法

    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;
        observer.mObserver.onChanged((T) mData);
    }

这个方法中主要是应该被激活状态下,调用观察者的onChanged方法 ,这样就回到我们被观察者中创建的观察回调。

你可能感兴趣的:(jetpack系列之Lifedata)