LiveData源码解析

上一篇文章 中分析了ViewModel的源码,其中提到了viewmodel要配合着LiveData来一起使用,那么今天来分析一下LiveData的源码,看看怎么用,有什么注意点。

第一部分:源码头文件翻译

/**
 * LiveData is a data holder class that can be observed within a given lifecycle.
   //这是一个可以被lifecycle对象用来观察数据变化的类。
 * This means that an {@link Observer} can be added in a pair with a {@link LifecycleOwner}, and
   //这就意味着一个被观察者可以被添加在多个lifecycleOwner(观察者)中
 * this observer will be notified about modifications of the wrapped data only if the paired
 * LifecycleOwner is in active state.
   //如果这个LifecycleOwner是处于活跃状态,才会收到被观察者数据改变的通知。
 * LifecycleOwner is considered as active, if its state is
 * {@link Lifecycle.State#STARTED} or {@link Lifecycle.State#RESUMED}. An observer added via
  //当观察者初始start/resume状态事,表示观察者是活跃状态。
 * {@link #observeForever(Observer)} is considered as always active and thus will be always notified
 * about modifications. 
  //如果调用observeForever方法添加的,那么观察者会被认为永远是活跃状态。
 * For those observers, you should manually call
 * {@link #removeObserver(Observer)}.
 //对于这些观察者,你应该(不用的时候)主动调用移除操作。
 * <p> An observer added with a Lifecycle will be automatically removed if the corresponding
 //如果这个观察者是Lifecycle或其子类,那么就会自动移除掉,不需要手动移除。
 * Lifecycle moves to {@link Lifecycle.State#DESTROYED} state. This is especially useful for
 * activities and fragments where they can safely observe LiveData and not worry about leaks:
 * they will be instantly unsubscribed when they are destroyed.
 //这个对于activity或者fragment是非常有用的,当他们被销毁前会自动删除。
 *
 * <p>
 * In addition, LiveData has {@link LiveData#onActive()} and {@link LiveData#onInactive()} methods
 * to get notified when number of active {@link Observer}s change between 0 and 1.
  //当观察者处于不同的状态时,livedata会调用onActive和onInactive方法。
 * This allows LiveData to release any heavy resources when it does not have any Observers that
 * are actively observing.
  //当没有任何观察者时,这个将允许liveData释放一些重的资源
 * <p>
 * This class is designed to hold individual data fields of {@link ViewModel},
 * but can also be used for sharing data between different modules in your application
 * in a decoupled fashion.
 //这个类的设计初衷是用来配合ViewModel一起使用的,当然也可以用来在不同的类或者不同的模块之间传递数据
 * @param <T> The type of data held by this instance
 * @see ViewModel
 */

我们可以知道如下几点:

1.这个类可以用来实现不同类、不同模块之间数据的传递

2.如果观察者不是Lifecycle的子类,那么需要我们手动解除他们之间的关系,如果是则无需关心

3.只有观察者处于活跃状态时,才会接收到数据改变的通知,当然也可以设置为任何时候都接收通知

4.这个类最初是设计配合viewmodel来实现MVVM架构的

第二部分:源码解析

LiveData是一个抽象类,我们如果使用需要用他的子类,这里我们来分析子类 MutableLiveData 的用法,因为这个类基本上就是完全继承LiveData,没有做任何额外操作:

public class MutableLiveData<T> extends LiveData<T> {

    public MutableLiveData(T value) {
        super(value);
    }

    public MutableLiveData() {
        super();
    }

    @Override
    public void postValue(T value) {
        super.postValue(value);
    }

    @Override
    public void setValue(T value) {
        super.setValue(value);
    }
}

我们先来看如何使用:

public class TextActivity extends ComponentActivity {

    private MutableLiveData<String> mLiveData;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //1.创建对象
        mLiveData = new MutableLiveData<String>();
        //2(3).添加观察者
        mLiveData.observe(this, new Observer<String>() {
            @Override
            public void onChanged(String s) {
                //4.接收到发送的数据
            }
        });
        //3(2).发送数据
        mLiveData.setValue("11111");
        //或者
        mLiveData.postValue("2222");

    }
}

1.创建对象

2.添加观察者

3.发送数据

4.观察者接收数据

其中2和3顺序可以颠倒,如果颠倒则为粘性事件

创建对象:

    public LiveData() {
        //初始化为Object
        mData = NOT_SET;
        //初始值为-1
        mVersion = START_VERSION;
    }

添加观察者:

    @MainThread
    public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) {
        //1.判断是否为主线程,如果不是则抛错误
        assertMainThread("observe");
        //2.判断activity或者fragment是否被销毁了
        if (owner.getLifecycle().getCurrentState() == DESTROYED) {
            // ignore
            return;
        }
        //3.创建一个LifecycleBoundObserver 对象,这个对象很关键
        LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer);
        //4.以观察者回调为key,放入hashmap中,如果重复添加,则报错
        ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper);
        if (existing != null) {
            throw new IllegalArgumentException("Cannot add the same observer"
                    + " with different lifecycles");
        }
        //5.activity或者fragment中获取Lifecycle,再保存wrapper
        owner.getLifecycle().addObserver(wrapper);
    }

1.判断是否为主线程,天剑观察者必须要在主线程中执行:

       //2(3).添加观察者
        mLiveData.observe(this, new Observer<String>() {
            @Override
            public void onChanged(String s) {
                //4.接收到发送的数据
            }
        });

2.判断activity或者fragment是否被销毁了

3.创建LifecycleBoundObserver,参数为activity或fragment和回调

4.以回调为key,LifecycleBoundObserver为value,保存到SafeIterableMap(双向链表)中,如果为重复添加则报错

5.第三步创建的LifecycleBoundObserver 添加到观察activity或者fragment的生命周期集合中,也就是说LifecycleBoundObserver 可以接收activity的生命周期回调了。

重点关注第3步:

//LiveData的内部类,ObserverWrapper 的子类
class LifecycleBoundObserver extends ObserverWrapper implements LifecycleEventObserver {
        @NonNull
        final LifecycleOwner mOwner;

        LifecycleBoundObserver(@NonNull LifecycleOwner owner, Observer<? super T> observer) {
            super(observer);
            mOwner = owner;
        }
        //判断activity是否为活跃状态
        @Override
        boolean shouldBeActive() {
            return mOwner.getLifecycle().getCurrentState().isAtLeast(STARTED);
        }
        //activity的生命周期改变监听回调
        @Override
        public void onStateChanged(@NonNull LifecycleOwner source,
                @NonNull Lifecycle.Event event) {
            Lifecycle.State currentState = mOwner.getLifecycle().getCurrentState();
            //如果activity被销毁了,则将观察者从回调中移除掉,这就是为什么我们无需主动移除原因
            if (currentState == DESTROYED) {
                //同时会调用detachObserver方法
                removeObserver(mObserver);
                return;
            }
            //判断当前activity状态是否和原来的不同,不同则回调父类ObserverWrapper中activeStateChanged方法
            Lifecycle.State prevState = null;
            while (prevState != currentState) {
                prevState = currentState;
                activeStateChanged(shouldBeActive());
                currentState = mOwner.getLifecycle().getCurrentState();
            }
        }

        @Override
        boolean isAttachedTo(LifecycleOwner owner) {
            return mOwner == owner;
        }
        //将自己从activity的生命周期观察者队列中移除
        @Override
        void detachObserver() {
            mOwner.getLifecycle().removeObserver(this);
        }
    }

这个类监听activity的生命周期主要做了如下操作:

1.只有activity的生命周期处于start之后才说明是处于活跃状态

2.当activity的生命周期改变的时候会调用onStateChanged方法,如果activity是销毁了,则将我们添加的回调移除掉,同时也会将activity的生命周期观察者从activity中移除掉,这也就为什么我只需要添加观察者,无需移除的原因。如果当前activity的状态和上一个状态不一致则,调用activeStateChanged方法,重点看看这个方法:

       void activeStateChanged(boolean newActive) {
            //如果activity都是处于活跃或者非活跃状态,则不需要回调,也就是说只有activity状态由活跃到非活跃状态或者反之,才需要继续执行下面操作
            if (newActive == mActive) {
                return;
            }
           
            mActive = newActive;
            //统计activity的活跃状态次数,如果由0-1>则调用onActive方法,否则调用onInactive方法
            changeActiveCounter(mActive ? 1 : -1);
            if (mActive) {
                //如果activity处于start状态之后,则调用这个方法
                dispatchingValue(this);
            }
        }

只有activity处于活跃状态改变时,才会继续执行,如果activity处于start状态之后,才会调用dispatchingValue方法:

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<Map.Entry<Observer<? super T>, ObserverWrapper>> iterator =
                        mObservers.iteratorWithAdditions(); iterator.hasNext(); ) {
                    //调用这个方法,参数为观察者回调
                    considerNotify(iterator.next().getValue());
                    if (mDispatchInvalidated) {
                        break;
                    }
                }
            }
        } while (mDispatchInvalidated);
        mDispatchingValue = false;
    }
private void considerNotify(ObserverWrapper observer) {
        //activity不是处于活跃状态,返回
        if (!observer.mActive) {
            return;
        }
       //再次检查activity是否处于活跃状态,不是则返回
        if (!observer.shouldBeActive()) {
            observer.activeStateChanged(false);
            return;
        }
        //ObserverWrapper 中最后一个版本是否大于当前版本,大于等于说明已经执行过了,无需重复执行,当前版本mVersion 会随着我们调用setValue或者postValue方法+1
        if (observer.mLastVersion >= mVersion) {
            return;
        }
        //重新给观察者最近版本赋值
        observer.mLastVersion = mVersion;
        //调用回调方法
        observer.mObserver.onChanged((T) mData);
    }

具体分析逻辑代码里写了,就不再赘述,总结一下:

1.将观察者保存起来

2.观察者和activity的生命周期绑定,观察activity的生命周期,销毁则自动解绑,接触耦合关系

3.activity的生命周期发生改变了,并且处于start状态及之后,则会校验最后一次执行回调的版本号是否大于等于当前版本号,如果小于则执行观察者回调

这里我们也可以知道livedata默认是发送粘性事件的,也就是说我们可以先发送事件,再添加观察者

再来看看发送数据方法:setValue

    @MainThread //必须在主线程执行
    protected void setValue(T value) {
        //判断是否为主线程
        assertMainThread("setValue");
        //记录数据版本号,用来和观察者接收版本号对比,防止多次发送同一个数据,也用来发送粘性事件
        mVersion++;
        mData = value;
        //直接调用分发数值方法
        dispatchingValue(null);
    }

方法很简单:必须在主线程执行,增加数据版本号,调用上面分析的分发值方法(查找观察者,校验观察者生命周期状态,校验数据版本号和观察者发送版本号,回调方法)

再来看看另一个发送数据的方法:postValue

     protected void postValue(T value) {
        //校验是否发送的内容为默认值object,是则放弃
        boolean postTask;
        synchronized (mDataLock) {
            postTask = mPendingData == NOT_SET;
            mPendingData = value;
        }
        if (!postTask) {
            return;
        }
        //切换到主线程发送数据
        ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable);
    }

先看看ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable):

    @Override
    public void postToMainThread(Runnable runnable) {
        if (mMainHandler == null) {
            synchronized (mLock) {
                if (mMainHandler == null) {
                    mMainHandler = createAsync(Looper.getMainLooper());
                }
            }
        }
        //noinspection ConstantConditions
        mMainHandler.post(runnable);
    }

就是用handler切换到了主线程,执行runnable任务:

    private final Runnable mPostValueRunnable = new Runnable() {
        @SuppressWarnings("unchecked")
        @Override
        public void run() {
            Object newValue;
            synchronized (mDataLock) {
                newValue = mPendingData;
                mPendingData = NOT_SET;
            }
            setValue((T) newValue);
        }
    };

又调用了setValue方法,所以postValue方法可以在任何线程中调用,回调还是在主线程中执行。源码分析完毕。

第三部分:不同类(activity或fragment)之间数据传值

思路1:LiveData设置为静态类变量

优缺点:简单,也不会发生内存泄漏问题,但是不方便管理

思路2:写一个LiveData工具类,用hashmap保存所有的LiveData,实现全局共享

优点:方便管理

我们使用思路2来实现一下:

public enum LiveDataUtils {
    INSTANCE;

    public static LiveDataUtils getsInstance() {
        return INSTANCE;
    }

    private HashMap<String, MutableLiveData> mLiveDataMap = new HashMap<>();

    public <T> MutableLiveData<T> getLiveData(Activity activity, Class<T> value) {
        MutableLiveData<T> mutableLiveData = mLiveDataMap.get(activity.getClass().getSimpleName() + value.getSimpleName());
        if (null == mutableLiveData) {
            mutableLiveData = new MutableLiveData<T>();
            mLiveDataMap.put(activity.getClass().getSimpleName() + value.getSimpleName(), mutableLiveData);
        }
        return mutableLiveData;
    }

    public <T> MutableLiveData<T> getLiveData(Fragment fragment,Class<T> value) {
        MutableLiveData<T> mutableLiveData = mLiveDataMap.get(fragment.getClass().getSimpleName() + value.getSimpleName());
        if (null == mutableLiveData) {
            mutableLiveData = new MutableLiveData<>();
            mLiveDataMap.put(fragment.getClass().getSimpleName() + value.getSimpleName(), mutableLiveData);
        }
        return mutableLiveData;
    }

    public <T> MutableLiveData<T> getLiveData(Class cla, Class<T> value) {
        MutableLiveData<T> mutableLiveData = mLiveDataMap.get(cla.getSimpleName() + value.getSimpleName());
        if (null == mutableLiveData) {
            mutableLiveData = new MutableLiveData<>();
            mLiveDataMap.put(cla.getSimpleName() + value.getSimpleName(), mutableLiveData);
        }
        return mutableLiveData;
    }
}

这样只要用的时候就可以直接获取,添加回调,其他任何页面发送事件就可以了。

第四部分:使用过程中的bug

1.如果A activity不是栈顶activity,A中添加了观察者,B页面多次setValue或者postValue,那么A activity只会响应最后一次数据,前面的全部都被覆盖掉了。

解决方案:

LiveDataUtils.getsInstance().getLiveData(this,Integer.class).observeForever( new Observer<Integer>() {
            @Override
            public void onChanged(Integer integer) {

            }
        });

使用observeForever 替代observe方法,并且需要在页面ondestory方法中添加,remvove方法,否则会发生内存泄漏。

LiveDataUtils.getsInstance().getLiveData(this,Integer.class).removeObserver();

2.去掉粘性事件,有些时候我们不想要粘性事件,那么可以参考

 LiveData去掉粘性事件 - 简书

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值