定义

LiveData 是一种可观察的数据存储器类。与常规的可观察类不同,LiveData 具有生命周期感知能力.
意指它遵循其他应用组件(如 Activity、Fragment 或 Service)的生命周期。 这种感知能力可确保 LiveData 仅更新处于活跃生命周期状态的应用组件观察者。
如果观察者(由 Observer 类表示)的生命周期处于 STARTED 或 RESUMED 状态,则 LiveData 会认为该观察者处于活跃状态。

我想从源码知道些什么内容

  • 数据如何感知生命周期?

Tip:
源码:Android API 29

LiveData 的使用

// 1. 在 ViewModel 中创建 LiveData 对象
class NameViewModel : ViewModel() {

    // Create a LiveData with a String
    val currentName: MutableLiveData<String> by lazy {
        MutableLiveData<String>()
    }

    // Rest of the ViewModel...
}

// 2. 在 组件中观察数据
class NameActivity : AppCompatActivity() {

	// Use the 'by viewModels()' Kotlin property delegate
	// from the activity-ktx artifact
	private val model: NameViewModel by viewModels()

	override fun onCreate(savedInstanceState: Bundle?) {
	    super.onCreate(savedInstanceState)

	    // 活跃状态下观察数据
	    model.currentName.observe(this, Observer<String> { newName ->
	        // Update the UI, in this case, a TextView.
	        nameTextView.text = newName
	    })

        // 所有状态下都能观察数据
        model.currentName.observeForever { user ->
            // update UI
            Log.e("currentName","currentName:$currentName")
        }

	    // 3. 通知数据更新
	    button.setOnClickListener {
	        val anotherName = "John Doe"
	        model.currentName.value = anotherName
	    }
	    
	}
}

参考示例:

  • Android Jetpack 库架构组件 ViewModel+LiveData 基础使用

通过使用我们可以找到几个关键点

  • MutableLiveData 是什么
  • MutableLiveDatasetValue()是如何工作的
  • MutableLiveData是如何通过observe观察数据的

MutableLiveData 是什么

进入到MutableLiveData源码发现它是继承了LiveData,并没做多余的操作。
那我们为什么不直接使用LiveData呢?

两个原因:

  1. LiveData是抽象类不能直接使用
  2. 设计成抽象类就是为了隐藏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);
    }
}

上面的代码中可以看出重写了两个方法

  • postValue
  • setValue

方法名就像设置数据,那么这两个方法有什么区别呢?

MutableLiveDatasetValue()是如何工作的

进入setValue方法,通过源码和注释,我们就知道了setValue 和 postValue的区别。

/**
 * Sets the value. If there are active observers, the value will be dispatched to them.
 * <p>
 * This method must be called from the main thread. If you need set a value from a background
 * thread, you can use {@link #postValue(Object)}
 *
 * @param value The new value
 */
@MainThread
protected void setValue(T value) {
    assertMainThread("setValue");
    // 订阅次数+1
    mVersion++;
    // 数据更新
    mData = value;
    // 分发指定的 ObserverWrapper
    dispatchingValue(null);
}

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

    // 子线程
    ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable);
}
  • setValue 在主线程调用
  • postValue 在子线程调用

这里的线程切换底层还是用的Handler实现。只不过这里又多封装了一层TaskExecutor 我们进入到postToMainThread方法

@Override
public void postToMainThread(Runnable runnable) {
    mDelegate.postToMainThread(runnable);
}

这里使用了mDelegate代理,如果没有设置代理则使用默认的DefaultTaskExecutor 进入到DefaultTaskExecutor可找到postToMainThread的实现。

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

ps:抽象类和子类,以及代理实现。让我又想起之前用ARouter做组件化开发使用的IProvider接口。BaseModule中定义接口,各个Module中实现,如果Module间需要联系即可通过BaseModule中定义的接口方法调用到不同Module在实现类的结果。

再回过头来看 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);
    }
};

可以看出这里的postValue还是会调用setValue

pps:源码中太多这种统一调用的操作了。比如 Retrofit 的同步异步调用,异步调用最后还是会执行同步方法。

setValue中调用了分发数据的方法dispatchingValue(null)

void dispatchingValue(@Nullable ObserverWrapper initiator) {

    // 在遍历通知各 ObserverWrapper 期间, 若数据发生了变化, 则会重新遍历
    // mDispatchingValue = true 表示数据发生了变化
    // mDispatchInvalidated = true 表示需要重新遍历

    if (mDispatchingValue) {
        mDispatchInvalidated = true;
        return;
    }

    mDispatchingValue = true;

    do {
        // 循环时:表示数据不需要重新遍历
        mDispatchInvalidated = false;

        // 若参数 initiator 非空,则只通知特定的 ObserverWrapper
        // 否则遍历通知所有的 ObserverWrapper
        if (initiator != null) {
            
            considerNotify(initiator);
            initiator = null;

        } else {
            for (Iterator<Map.Entry<Observer<? super T>, ObserverWrapper>> iterator =
                    mObservers.iteratorWithAdditions(); iterator.hasNext(); ) {

	        	// 通知观察者,这个观察者是 ObserverWrapper 类型的。
                considerNotify(iterator.next().getValue());

                // 若数据发生变化, 则退出for循环
                if (mDispatchInvalidated) {
                    break;
                }
            }
        }
    } while (mDispatchInvalidated);

    // 循环结束,将数据需要遍历的标识符改为 false
    mDispatchingValue = false;
}

// 而分发数据逻辑中就是循环遍历告知所有的观察者
private void considerNotify(ObserverWrapper observer) {

    // 不在活跃状态,直接 return
    if (!observer.mActive) {
        return;
    }
    
    // 不是在活跃状态 则设置活跃状态为 false 且不去通知观察者,直接 return
    if (!observer.shouldBeActive()) {
        observer.activeStateChanged(false);
        return;
    }

    // mVersion 表示发送订阅的次数
    // 当调用 setValue 之后 mVersion 会加1,所以说在数据发送变化时才会去通知观察者,否则直接 return
    if (observer.mLastVersion >= mVersion) {
        return;
    }

    // 更新最后一次通知观察者的版本号
    observer.mLastVersion = mVersion;
    // 通知观察者
    observer.mObserver.onChanged((T) mData);
}

既然通知到位了,那接下来看注册的通知如何在活跃状态下更新数据。

MutableLiveData是如何通过observe观察数据的

我们调用observe的去监听数据更新的代码如下:

model.userInfo.observe(this, Observer<User>{ user ->
        // update UI
        Log.e("GardenActivity","user:$user")
    })

进入observe源码可以看出该方法要在主线程调用,上面传入的this参数是LifecycleOwner,并通过这个LifecycleOwner获取到LifeCycle 进而调用LifeCycleaddObserver方法实现数据对组件生命周期的感知。

// 只在活跃状态下接收数据
@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);
}

这里的addObserver(wrapper)的参数传入了LifecycleBoundObserver对象
进入LifecycleBoundObserver可以查看到

  • onStateChanged : state变化的回调,在DESTROYED时将观察者移除
  • detachObserver:在里面也移除了当前的观察者

可见在LiveDate内部是处理内存泄漏的问题。

而且shouldBeActive方法中返回了活跃状态,也就是组件只在活跃状态下更新数据

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() {
        // 大于等于 STARTED 的值才是活跃的状态:这里就只有 STARTED 和 RESUMED
        // STARTED:onStart()之后onPause()之前的生命周期
        // RESUMED:onResume()  之前的生命周期
        // 所以说 LiveData 只在活跃状态下更新数据,就是在:onStart()、onPause()、onResume() 这三个生命周期下会回调数据更新。
        return mOwner.getLifecycle().getCurrentState().isAtLeast(STARTED);
    }

    @Override
    public void onStateChanged(@NonNull LifecycleOwner source,
            @NonNull Lifecycle.Event event) {
        if (mOwner.getLifecycle().getCurrentState() == DESTROYED) {
            removeObserver(mObserver);
            return;
        }

        // 更改活跃状态
        activeStateChanged(shouldBeActive());
    }

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

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

而跟LifecycleBoundObserver相对于的是AlwaysActiveObserver类,这个是保持所有的观察者都所欲活跃状态。

private class AlwaysActiveObserver extends ObserverWrapper {

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

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

相应的监听方法是observeForever

// 在所有状态下组件都接收数据
@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);
}

// 更改活跃状态
void activeStateChanged(boolean newActive) {
    if (newActive == mActive) {
        return;
    }
    // immediately set active state, so we'd never dispatch anything to inactive
    // owner
    mActive = newActive;
    boolean wasInactive = LiveData.this.mActiveCount == 0;
    LiveData.this.mActiveCount += mActive ? 1 : -1;

    if (wasInactive && mActive) {
        onActive();
    }
    if (LiveData.this.mActiveCount == 0 && !mActive) {
        onInactive();
    }
    // 分发数据
    if (mActive) {
        // 循环通知观察者
        dispatchingValue(this);
    }
}

addObserver的实现是由LiveData的实现类LifecycleRegistry实现了。

关于LifeCycle如何绑定生命周期,更多源码可以查看:带着问题看源码之 LifeCycler。

所以LiveData中的数据能够感知组件的生命周期变化,实际上是用了LifeCycle去实现。

总结

  • MutableLiveData 是什么
    LiveData的实现类,提供了公开的postValue、setValue方法用于数据改变
  • MutableLiveDatasetValue()是如何工作的
    每次setValue计数器加1,同时数据变为最新的数据,调用dispatchingValue(null)分发指定的ObserverWrapper 当数据再次改变时会调用dispatchingValue(ObserverWrapper)循环分发所有活跃状态的的数据。如果之前的数据还在下发则停止下发并重头开始下发
  • MutableLiveData是如何通过observe观察数据的
    这是在活跃状态下观察数据的方法,活跃状态是:onStart,onPause,onResume。
    内部检测生命周期使用的是LifeCycle

observe对应的还有observeForever,它能在所有状态下观察到数据。

参考

  • LiveData 概览
  • Android官方架构组件LiveData: 观察者模式领域二三事
  • Android Jetpack 库架构组件 ViewModel+LiveData 基础使用