yunshuipiao / Potato

Read the fucking source code for the Android interview
Apache License 2.0
80 stars 12 forks source link

AAC: LiveData #38

Open yunshuipiao opened 5 years ago

yunshuipiao commented 5 years ago

AAC: LiveData

[TOC]

对比 mvp 而言,使用大量的接口在 逻辑层和UI 层之间通信,AAC 则使用 livedata 进行通信。

基本使用

下面简单的演示如何在两者进行通信:

// MainActivity.java
override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)
    viewModel = ViewModelProviders.of(this).get(MainViewModel::class.java)
    bindData()
    initView()
}

   private fun bindData() {
        Log.d(TAG, "MainActivity on create, ${lifecycle.currentState}")
        lifecycle.addObserver(LifeCycleObject())
        val addOneObserver = object : Observer<Int> {
            override fun onChanged(t: Int?) {
                Log.d(TAG, "-- $t ")
            }
        }
        viewModel.resultLiveData.observe(this, addOneObserver)
    }

    private fun initView() {
        addone.setOnClickListener { viewModel.addOne() }
    }

class MainViewModel : ViewModel() {
    var resultLiveData = MutableLiveData<Int>()

    fun addOne() {
        val value: Int? = resultLiveData.value
        // dosomething
        Log.d(TAG, "model -- $value")
        resultLiveData.postValue((value ?: 0) + 1)
    }
}

输出结果如下:

ainActivity: model -- null
D/MainActivity: -- 1 
D/MainActivity: model -- 1
D/MainActivity: -- 2 
D/MainActivity: model -- 2
D/MainActivity: -- 3 
D/MainActivity: model -- 3
D/MainActivity: -- 4 

可以看到无论调用 addOne() 几次,都在回调之前执行,只输入一次结果,带着问题往下看源码。

源码分析

public class MutableLiveData<T> extends LiveData<T> {
    @Override
    public void postValue(T value) {
        super.postValue(value);
    }

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

public abstract class LiveData<T> {
    @SuppressWarnings("WeakerAccess") /* synthetic access */
    final Object mDataLock = new Object();
    static final int START_VERSION = -1;
    @SuppressWarnings("WeakerAccess") /* synthetic access */
    static final Object NOT_SET = new Object();

  // map 保存观察者
    private SafeIterableMap<Observer<? super T>, ObserverWrapper> mObservers =
            new SafeIterableMap<>();
    ... 
}

下面看一下 bindData 的内容。

private fun bindData() {
    Log.d(TAG, "MainActivity on create, ${lifecycle.currentState}")
    lifecycle.addObserver(LifeCycleObject())
    val addOneObserver = object : Observer<Int> {
        override fun onChanged(t: Int?) {
            Log.d(TAG, "-- $t ")
        }
    }
    viewModel.resultLiveData.observe(this, addOneObserver)
}
val addOneObserver = object : Observer<Int> {
    override fun onChanged(t: Int?) {
        Log.d(TAG, "-- $t ")
    }
}
public interface Observer<T> {
    /**
     * Called when the data is changed.
     * @param t  The new data
     */
    void onChanged(T t);
}
// LiveData.java
@MainThread
public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) {
    // 必须在主线程
    assertMainThread("observe");
    // DESTROyED 状态不观察
    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;
    }
    // 回到 LifeCycle
    owner.getLifecycle().addObserver(wrapper);
}

下面看一下 ViewModel 的结果如何通知到 UI 层面。

// LiveData.java
protected void postValue(T value) {
    boolean postTask;
    synchronized (mDataLock) {
        // 值设置过,才会进行处理
        postTask = mPendingData == NOT_SET;
        mPendingData = value;
    }
    if (!postTask) {
        return;
    }
    ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable);
}

这里的方法需要说明一下,由于 postValue 可以执行在线程池,所以结果时抛到主线程去执行;因此对于一下结果:

liveData.postValue("a");
liveData.setValue("b");

b 首先会被设置,然后再设置a。

另外,如果在主线程执行完毕之前 post 多次结果,只有最后的一次结果会回调分发。

private final Runnable mPostValueRunnable = new Runnable() {
    @Override
    public void run() {
        Object newValue;
        synchronized (mDataLock) {
            newValue = mPendingData;
            // 恢复状态
            mPendingData = NOT_SET;
        }
        //noinspection unchecked
        setValue((T) newValue);
    }
};

    @MainThread
    protected void setValue(T value) {
        assertMainThread("setValue");
        mVersion++;
        mData = value;
        dispatchingValue(null);
    }
void dispatchingValue(@Nullable ObserverWrapper initiator) {
    // 正在分发
    if (mDispatchingValue) {
        mDispatchInvalidated = true;
        return;
    }
    mDispatchingValue = true;
    do {
        mDispatchInvalidated = false;
        if (initiator != null) {
            considerNotify(initiator);
            initiator = null;
        } else {
            // 对所有的观察者进行 value 分发
            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) {
    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.
    // 检查 UI 的状态,必须满足状态大于 STARTED。
    if (!observer.shouldBeActive()) {
        observer.activeStateChanged(false);
        return;
    }
    // value 更改的次数
    if (observer.mLastVersion >= mVersion) {
        return;
    }
    observer.mLastVersion = mVersion;
    //noinspection unchecked
    // 回调通知新的 value。
    observer.mObserver.onChanged((T) mData);
}

总结

LiveData 相当于 UI 和 ViewModel 之前的桥梁,当 UI 产生执行动作,而 ViewModel 执行逻辑,从数据库或者网络拿到数据后, 从不同线程使用 livedata postvalue 到 UI 进行操作。

是为 MVVM 架构, 也是数据驱动, 响应式编程的表现。