LiveData源码解析

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

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

看源码前先考虑下如果要自己实现 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源码解析》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

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

Advanced Web Metrics with Google Analytics, 2nd Edition

Advanced Web Metrics with Google Analytics, 2nd Edition

Brian Clifton / Sybex / 2010-3-15 / USD 39.99

Valuable tips and tricks for using the latest version of Google Analytics Packed with insider tips and tricks, this how-to guide is fully revised to cover the latest version of Google Analytics and sh......一起来看看 《Advanced Web Metrics with Google Analytics, 2nd Edition》 这本书的介绍吧!

CSS 压缩/解压工具
CSS 压缩/解压工具

在线压缩/解压 CSS 代码

图片转BASE64编码
图片转BASE64编码

在线图片转Base64编码工具

随机密码生成器
随机密码生成器

多种字符组合密码