Jetpack-LiveData浅析

157 阅读2分钟

LiveData是什么?

LiveData 是 Jetpack 中的一个组件。LiveData是一种可观察的数据存储器类,LiveData具有生命周期感知能力,这种感知能力可确保LiveData仅更新处于活跃生命周期状态的应用组件观察者。LiveData一般配合ViewModel使用。

LiveData的使用

class CommonViewModel:ViewModel() {

    val commonData: MutableLiveData<String> = MutableLiveData()

    fun updateContent(name: String) {
        // liveData的第一种发送数据的方法
        //commonData.postValue(name)
        // liveData的第二种发送数据的方法
        //commonData.setValue(name)
    }
}

通过在ViewModel中创建MutableLiveData对象,然后调用liveData的postValue()或者setValue()进行数据的发送。

//只在活跃状态下才能收到数据变更
mViewModel.commonData.observe(this) {
// 进行数据的接收
}
//不区分是否活跃都能收到数据变更
mViewModel.commonData.observeForever {
// 进行数据的接收
}

在Activity/Fragment中通过liveData的observe方法进行数据的接收。

对于上面livaData的两种发送数据的方法的区别是:

setValue()只能在主线程调用。

postValue()可以在子线程调用,但是最终还是会调用setValue()进行数据的发送。

LiveData的原理

LiveData的原理非常简单。它使用观察者模式来通知观察者数据发生了变化。当LiveData对象被观察时,它会将观察者添加到观察者列表中。当LiveData对象发生变化时,它会通知观察者。为了避免内存泄漏,LiveData还需要与生命周期组件一起使用,以确保观察者只会在活动的生命周期内接收数据更新。

LiveData通过与Lifecycle组件配合使用,实现了对观察者的自动添加和移除。当Activity或Fragment处于STARTED或RESUMED状态时,LiveData会将观察者添加到观察者列表中,并开始向观察者发送数据更新通知。当Activity或Fragment处于STOPPED或DESTROYED状态时,LiveData会自动将观察者从观察者列表中移除,停止向其发送数据更新通知。这样一来,我们就不必手动管理LiveData的观察者订阅和取消订阅,极大地简化了代码的编写和维护。

LiveData的数据粘性

在 LiveData 中,数据粘性是指当LiveData中的数据发生变化时,即使观察者在数据变化之后才注册,也能立即收到最新的数据变化通知。

public class NoStickyLivaData<T> extends LiveData {

    private boolean stickFlag = false;

    @Override
    public void observe(@NonNull LifecycleOwner owner, @NonNull Observer observer) {
        super.observe(owner, observer);
        if (!stickFlag) {
            hook(observer);
            stickFlag = true;
        }
    }

    private void hook(Observer<? super T> observer) {
        //1.得到mLastVersion
        // 获取到LiveData的类的mObservers对象
        // SafeIterableMap<Observer<? super T>, ObserverWrapper> mObservers
        try {
            Class<LiveData> aClass = LiveData.class;
            Field mObservers = aClass.getDeclaredField("mObservers");
            mObservers.setAccessible(true);
            //获取到这个成员变量的对象 new SafeIterableMap<>()
            Object mObserversObject = mObservers.get(this);
            Class<?> mObserversClass = mObserversObject.getClass();
            Method get = mObserversClass.getDeclaredMethod("get", Object.class);
            get.setAccessible(true);
            //执行get方法   mObservers.get(observer)
            Object invokeEntry = get.invoke(mObserversObject,observer);
            Object observerWrapper = null;
            if (invokeEntry != null && invokeEntry instanceof Map.Entry) {
                observerWrapper = ((Map.Entry)invokeEntry).getValue();
            }
            if (observerWrapper == null) {
                throw new NullPointerException("observerWraper is null");
            }
            Class<?> superclass = observerWrapper.getClass().getSuperclass();
            Field mLastVersion = superclass.getDeclaredField("mLastVersion");
            mLastVersion.setAccessible(true);
            // 2.得到mVersion
            Field mVersion = aClass.getDeclaredField("mVersion");
            mVersion.setAccessible(true);
            //3.把mVersion的数据填入到mLastVersion中
            Object mVersionValue = mVersion.get(this);
            mLastVersion.set(observerWrapper,mVersionValue);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

解决方式是反射更改版本号,使observer.mLastVersion 和 mVersion相同。