LiveData使用方法、原理分析

182 阅读4分钟

RE4wEad.jpeg

Jetpack系列:
Lifecycle使用方法、原理分析 - 掘金 (juejin.cn)
LiveData使用方法、原理分析 - 掘金 (juejin.cn)
ViewModel使用方法、原理分析(一) - 掘金 (juejin.cn)
ViewModel使用方法、原理分析(二) - 掘金 (juejin.cn)
自定义View中获取ViewModel - 掘金 (juejin.cn)

LiveData 使用方法、原理分析

1.常规使用方法

/**
* liveData 将setValue()&postValue()  设置protected 对外不暴露
* MutableLiveData 继承LiveData,对外公开setValue()&postValue(),初始化对外暴露LiveData类型
* 
**/
private val _data:MutableLiveData<String> = MutableLiveData("A")
val data:LiveData<String> = _data

viewModel.data.observe(this) { it ->
    Log.d("CustomViewActivity", "=======it:$it")
}

viewModel.data.observeForever {it->  
    Log.d("CustomViewActivity""=======it:$it")  
}

2.LiveData原理分析

LiveData源码中只有3个类,LiveData(抽象类)、MutableLiveData(实现类)、Observer(接口类、回调)

Observer.java

public interface Observer<T> {
    /**
     * Called when the data is changed.
     * @param t  The new data
     */
    void onChanged(T t);
}

在LiveData中内部类ObserverWrapper

  • 重点activeStateChanged(),状态发生改变时分发数据(只有在激活状态下);
  • changeActiveCounter()会记录当前liveData所持有observer数量,会回调active()&inactive()
  • 有两个实现类 AlwaysActiveObserver、LifecycleBoundObserver,分别对应observeForever、obverve;
private abstract class ObserverWrapper {
    final Observer<? super T> mObserver;
    boolean mActive;
    int mLastVersion = START_VERSION;

    ObserverWrapper(Observer<? super T> observer) {
        mObserver = observer;
    }

    abstract boolean shouldBeActive();

    boolean isAttachedTo(LifecycleOwner owner) {
        return false;
    }

    void detachObserver() {
    }

    void activeStateChanged(boolean newActive) {
        if (newActive == mActive) {
            return;
        }
        // immediately set active state, so we'd never dispatch anything to inactive
        // owner
        mActive = newActive;
        changeActiveCounter(mActive ? 1 : -1);
        if (mActive) {
            dispatchingValue(this);
        }
    }
}

/***
* observeForever() 设置监听Observer对象
***/
private class AlwaysActiveObserver extends ObserverWrapper {

    AlwaysActiveObserver(Observer<? super T> observer) {
        super(observer);
    }

    @Override
    boolean shouldBeActive() {
        return true;
    }
}

/***
* 实现LifecycleEventObserver接口,根据 LifecycleObserver 生命周期变化判断是否分发数据
* LiveData精华所在,根据生命周期变化更新数据
***/
class LifecycleBoundObserver extends ObserverWrapper implements LifecycleEventObserver {
    @NonNull
    final LifecycleOwner mOwner;

    LifecycleBoundObserver(@NonNull LifecycleOwner owner, Observer<? super T> observer) {
        super(observer);
        mOwner = owner;
    }

    @Override
    boolean shouldBeActive() {
        return mOwner.getLifecycle().getCurrentState().isAtLeast(STARTED);
    }


    @Override
    public void onStateChanged(@NonNull LifecycleOwner source,
            @NonNull Lifecycle.Event event) {
        Lifecycle.State currentState = mOwner.getLifecycle().getCurrentState();
        if (currentState == DESTROYED) {
            removeObserver(mObserver);
            return;
        }
        Lifecycle.State prevState = null;
        while (prevState != currentState) {
            prevState = currentState;
            activeStateChanged(shouldBeActive());
            currentState = mOwner.getLifecycle().getCurrentState();
        }
    }

    @Override
    boolean isAttachedTo(LifecycleOwner owner) {
        return mOwner == owner;
    }

    @Override
    void detachObserver() {
        mOwner.getLifecycle().removeObserver(this);
    }
}

对Observer进行封装, owner.getLifecycle().addObserver(wrapper)对生命周期进行监听; 而observeForever wrapper.activeStateChanged(true)设置一直处于激活状态,不跟随生命周期变化

@MainThread
public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> 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);
}

@MainThread
public void observeForever(@NonNull Observer<? super T> observer) {
    assertMainThread("observeForever");
    AlwaysActiveObserver wrapper = new AlwaysActiveObserver(observer);
    ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper);
    if (existing instanceof LiveData.LifecycleBoundObserver) {
        throw new IllegalArgumentException("Cannot add the same observer"
                + " with different lifecycles");
    }
    if (existing != null) {
        return;
    }
    wrapper.activeStateChanged(true);
}

3.setValue() & postValue()区分

postValue()通过线程将数据发送,会存在发送数据丢失等问题,实际执行切换线程操作,在连续多次调用后,mPendingData会被赋予最新值,在mPostValueRunnable中会将最新的mPendingData设置为最后一次值**


@MainThread
protected void setValue(T value) {
    assertMainThread("setValue");
    mVersion++;
    mData = value;
    dispatchingValue(null);
}

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

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



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;
}

关于网络流传LiveData “粘性”问题

首先需要弄清楚一个问题,UI界面接收的数据、事件区分来分析,数据粘性用于UI显示本身是没有问题的,LiveData本身设计初衷解决UI界面显示,比如:用户登录成功后显示头像+用户名等相关信息,在不同界面通过LiveData传递数据就是合理的

再继续用登录场景进行模拟,如果在用户名、密码输入错误时进行Toast提示,如果此时用LiveData传递这个登录失败提示时就会出现再每次回到这个界面时,或者屏幕旋转导致Activity生命周期重新执行时,就会出现多次Toast提示,不符合业务场景需求,可以理解会为事件,MVI架构设计思路大致也是如此

反射方案修改LiveData.observer()中的Observer的mLastVersion解决:

class NoStickMutableLiveData<T> constructor(private var isStick:Boolean = false): MutableLiveData<T>(){

    override fun observe(owner: LifecycleOwner, observer: Observer<in T>) {
        super.observe(owner, observer)
        if (!isStick){
            hook(observer)
        }
    }

    override fun observe(owner: LifecycleOwner, observer: Observer<in T>) {
        super.observe(owner, observer)
        if (!isStick){
            hook(observer)
        }
    }

    private fun hook(observer: Observer<in T>){
        val liveDataClass = LiveData::class.java

        val mObserverFiled = liveDataClass.getDeclaredField("mObservers")
        mObserverFiled.isAccessible = true

        val mObserversMap:Any = mObserverFiled.get(this)
        val mObserversMapClass = mObserversMap.javaClass

        val mObserversMapGet = mObserversMapClass.getDeclaredMethod("get",Any::class.java)
        mObserversMapGet.isAccessible=true

        var observerWrapper:Any? 
        val invokeEntry = mObserversMapGet.invoke(mObserversMap, observer)
        if (invokeEntry != null && invokeEntry is Map.Entry<*, *>){
            observerWrapper = invokeEntry.value
        }else{
            throw Exception("observerWrapper  error")
        }
        val observerWrapperSuperClass = observerWrapper?.javaClass?.superclass
        val mLastVersionField = observerWrapperSuperClass?.getDeclaredField("mLastVersion")
        mLastVersionField?.isAccessible = true
        val mLastVersion = mLastVersionField?.get(observerWrapper)
        Log.d("NoStickMutableLiveData", "mLastVersion:$mLastVersion")

        val mVersionFiled = liveDataClass.getDeclaredField("mVersion")
        mVersionFiled.isAccessible=true
        val mVersion = mVersionFiled.get(this)
        Log.d("NoStickMutableLiveData", "mVersion:$mVersion")

        mLastVersionField?.set(observerWrapper, mVersion)
    }
}

关于LiveData粘性事件所带来问题的解决方案 - 简书 (jianshu.com)
不做跟风党,LiveData,StateFlow,SharedFlow 使用场景对比 - 掘金 (juejin.cn)