LiveData源码解析

栏目: IOS · Android · 发布时间: 6年前

内容简介:看源码前先考虑下如果要自己实现基本做法:扩展:

看源码前先考虑下如果要自己实现 LiveData 应该怎么做?

基本做法:

setter
Observer

扩展:

  1. 允许子线程更新数据, 因此 setter 需要考虑同步;
  2. 项目中可能多个地方需要用到目标数据,因此回调监听器可以添加多个;
  3. 数据变化时常常都需要更新UI,而UI有生命周期,因此 Observer 需要提供 Lifecycle 相关逻辑支持,包括:
    1. 定义处于哪些生命周期的 Observer 可以收到数据更新;
    2. onDestroy() 时自动移除 Observer 等;
  4. 如何定义 数据变化 呢? 最简单直接的做法是每次触发 setter 方法时都当作数据发生了变化, 遍历通知所有 Observer 即可, 更进一步的判定交给调用方; ......

简单使用

// 定义 livedata
object ParaConfig {
    // 定义一个私有的 `MutableLiveData`
    private val msgLiveData = MutableLiveData<String>()

    // 开放给外部获取数据更新时,提供不可变的 `LiveData` 即可;
    fun getMsgLiveData(): LiveData<String> = msgLiveData

    fun updateMsg(msg: String, inBgThread: Boolean = false) {
        if (inBgThread) {
            msgLiveData.postValue(msg) // 在子线程中更新数据
        } else {
            msgLiveData.value = msg // 在主线程中更新数据
        }
    }
}
复制代码
// 添加 `Observer`
class LiveDataFrag : Fragment() {
    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)

        // 添加一个跟生命周期相关的 `Observer`
        ParaConfig.getMsgLiveData().observe(this, Observer<String> { newMsg ->
            tv_msg.text = newMsg
        })

        // 无视生命周期, 每次数据变化时都会回调,需要自行移除observer
        ParaConfig.getMsgLiveData().observeForever {
            Logger.d("observeForever: $it","tag_livedata")
        }
    }
}
复制代码

看源码我还是习惯从调用入口一步步往下看, 以下也是按照这种顺序来;

实现

LiveData源码解析

添加 Observer

// LiveData.java
public abstract class LiveData<T> {
    private static final Object NOT_SET = new Object();
    // 实际数据,类型为 Object 而非 T
    private volatile Object mData = NOT_SET;
    // 存储所有的 Observer
    private SafeIterableMap<Observer<T>, ObserverWrapper> mObservers = new SafeIterableMap<>();

    // 添加跟生命周期相关的 observer
    // 目标数据
    @MainThread
    public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<T> observer) {
        // 若 LifecycleOwner 已处于已被销毁,则忽略该 observer
        if (owner.getLifecycle().getCurrentState() == DESTROYED) {
            return;
        }

        // 将 LifecycleOwner 和 Observer 功能进行绑定包装
        // 生成支持生命周期感知的 Observer: LifecycleBoundObserver
        LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer);
        // 避免重复添加相同的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;
        }

        // 实现对 LifecycleOwner 生命周期的感知
        // 关键还是 LifecycleBoundObserver 类,我们马上进去看一下
        owner.getLifecycle().addObserver(wrapper);
    }

    // 无视生命周期, 每次数据发生变化时,都会回调通知 Observer
    // 需要手动在不需要时移除 Observer
    @MainThread
    public void observeForever(@NonNull Observer<T> observer) {
        AlwaysActiveObserver wrapper = new AlwaysActiveObserver(observer);
        ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper);
        if (existing != null && existing instanceof LiveData.LifecycleBoundObserver) {
            throw new IllegalArgumentException("Cannot add the same observer"
                    + " with different lifecycles");
        }
        if (existing != null) {
            return;
        }
        wrapper.activeStateChanged(true);
    }
}
复制代码

MutableLiveData 只是简单重写了 LiveDatasetValue(T) / postValue(T) 方法, 改为 public 而已;

数据如何传递的: setValue(T) 解析

// LiveData.java
@MainThread
protected void setValue(T value) {
    // 只能在UI线程中调用,否则抛出异常,崩溃
    assertMainThread("setValue");
    mVersion++;
    mData = value;
    dispatchingValue(null);
}

private boolean mDispatchingValue;

// 若参数 initiator 非空,则表示只通知特定的 ObserverWrapper, 否则是回调通知所有 ObserverWrapper
// 由于只在主线程中调用,因此不用做多线程处理
private void dispatchingValue(@Nullable ObserverWrapper initiator) {
    // 小技巧: 在遍历通知各 ObserverWrapper 期间, 若数据发生了变化, 则会重新遍历通知
    if (mDispatchingValue) {
        mDispatchInvalidated = true;
        return;
    }

    mDispatchingValue = true;
    do {
        mDispatchInvalidated = false;
        if (initiator != null) {// initiator 非空时,只更新特定 ObserverWrapper
            considerNotify(initiator); // 实际更新数据的方法
            initiator = null;
        } else { // 否则遍历更新所有 ObserverWrapper
            for (Iterator<Map.Entry<Observer<T>, ObserverWrapper>> iterator =
                    mObservers.iteratorWithAdditions(); iterator.hasNext(); ) {
                considerNotify(iterator.next().getValue());
                // 若数据发生变化, 则退出for循环
                // 而外层 do...while() 判定条件为true,就会重新遍历通知各 ObserverWrapper;
                if (mDispatchInvalidated) {
                    break;
                }
            }
        }
    } while (mDispatchInvalidated);
    mDispatchingValue = false;
}

// 判断是否要将数据分发到指定的 ObserverWrapper
private void considerNotify(ObserverWrapper observer) {
    // 是否可以分发数据到指定的 observer, 由 mActive 来控制
    // 所以 mActive 很重要,具体下一节解读
    if (!observer.mActive) {
        return;
    }

    // 二次确认状态, 可能生命周期发生了变化,但 mActive 并未改变
    if (!observer.shouldBeActive()) {
        // active -> inactive 时通知更新状态
        // inactive 状态下就不需要分发数据了
        observer.activeStateChanged(false);
        return;
    }

    // 若 ObserverWrapper 持有的数据值已是最新版本, 自然也不用分发
    if (observer.mLastVersion >= mVersion) {
        return;
    }
    observer.mLastVersion = mVersion;

    // 通知 observer 数据有更新
    // observer.mObserver 是调用方实际传入的
    observer.mObserver.onChanged((T) mData);
}
复制代码

用于子线程调用的 postValue(T) 会发射一个 Runnable 到主线程中, 最终也是通过 setValue(T) 来实现数据分发; 当然, postValue(T) 也可以在主线程调用,不过是多此一举,如:

// observer会先收到 "msgFromSetValue" 然后才收到 "msgFromPostValue"
someBtnView.setOnClickListener {
    msgLiveData.postValue("msgFromPostValue")
    msgLiveData.value = "msgFromSetValue"
}
复制代码

ObserverWrapper 类解析

LiveData源码解析
// LiveData 的内部抽象类
// 包装用户传入的 Observer, 提供数据版本记录以及active状态(生命周期)判断
private abstract class ObserverWrapper {
    final Observer<T> mObserver;
    boolean mActive; // 确定当前 ObserverWrapper 是否生效,true时才可进行数据更新
    int mLastVersion = START_VERSION; // 当前持有的数据版本号,初始值为 -1

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

    // 判断该 Observer 是否有效, true 时才会触发 activeStateChanged()
    abstract boolean shouldBeActive();

    boolean isAttachedTo(LifecycleOwner owner) {
        return false;
    }

    void detachObserver() {
    }

    // 更新本 ObserverWrapper 的状态
    void activeStateChanged(boolean newActive) {
        // 若状态没变化,不需要更新,直接返回
        if (newActive == mActive) {
            return;
        }

        mActive = newActive;
        boolean wasInactive = LiveData.this.mActiveCount == 0;
        LiveData.this.mActiveCount += mActive ? 1 : -1;

        // 处于 active 状态的 observer 数量从0 -> 1时,触发 onActive() 方法
        if (wasInactive && mActive) {
            onActive();
        }

        // 处于 active 状态的 observer 数量从 1 -> 0时,触发 onInactive() 方法
        // 提供给观察者释放资源的机会
        if (LiveData.this.mActiveCount == 0 && !mActive) {
            onInactive();
        }

        // observer 从  inactive -> active 时, 更新数据
        if (mActive) {
            // 将数据发送给该 observer
            dispatchingValue(this);
        }
    }
}
复制代码

此类并未给出 inactive/active 具体是何种状态, 具体应是由 shouldBeActive() 来确定, 因此需要从子类查找;

子类 AlwaysActiveObserver 比较简单, 只是将 shouldBeActive() 固定返回 true ,表示一直生效, 每次数据发生变化时都需要发送通知; 我们看下 LifecycleBoundObserver 类;

LifecycleBoundObserver 解析

// LiveData 内部类
// 将 LifecycleObserver 和 ObserverWrapper 结合,当生命周期变化时,通知 ObserverWrapper 更新数据
class LifecycleBoundObserver extends ObserverWrapper implements GenericLifecycleObserver {
    @NonNull final LifecycleOwner mOwner;

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

    @Override
    boolean shouldBeActive() {
        // 此处定义了哪些生命周期是 `active` 的
        // 结合 Lifecycle.State 类 ,我们知道是: STARTED/RESUMED 两种状态
        // 对应于生命周期 `onStart()` 之后到 `onStop()` 之前
        return mOwner.getLifecycle().getCurrentState().isAtLeast(STARTED);
    }

    // 生命周期变化时回调本方法
    @Override
    public void onStateChanged(LifecycleOwner source, Lifecycle.Event event) {
        // 若当前 LifecycleOwner onDestory() 了, 则自动移除 observer, 避免内存泄露
        if (mOwner.getLifecycle().getCurrentState() == DESTROYED) {
            removeObserver(mObserver);
            return;
        }
        // 将 shouldBeActive() 返回的状态当做本 ObserverWrapper 的状态
        // 即  mActive = shouldBeActive()
        activeStateChanged(shouldBeActive());
    }

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

    @Override
    void detachObserver() {
        mOwner.getLifecycle().removeObserver(this);
    }
}
复制代码

以上所述就是小编给大家介绍的《LiveData源码解析》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Build Your Own Web Site the Right Way Using HTML & CSS

Build Your Own Web Site the Right Way Using HTML & CSS

Ian Lloyd / SitePoint / 2006-05-02 / USD 29.95

Build Your Own Website The Right Way Using HTML & CSS teaches web development from scratch, without assuming any previous knowledge of HTML, CSS or web development techniques. This book introduces you......一起来看看 《Build Your Own Web Site the Right Way Using HTML & CSS》 这本书的介绍吧!

JSON 在线解析
JSON 在线解析

在线 JSON 格式化工具

RGB HSV 转换
RGB HSV 转换

RGB HSV 互转工具

HSV CMYK 转换工具
HSV CMYK 转换工具

HSV CMYK互换工具