写点什么

[JetPack] LiveData 源码解析

用户头像
Changing Lin
关注
发布于: 2021 年 01 月 22 日
[JetPack] LiveData源码解析

1. 背景 官网LiveData

    笔者在开发一款即时通讯和音视频应用时,发现需要花费很大的力量去处理系统组件之间的数据传递,稍微有点不注意,就会出现状态错乱不同步的问题,影响用户体验,也给系统稳定性带来了许多挑战。因此,在我们 2.0 版本的重构过程中,毅然决定引入 LiveData,经过实践证明,其是一种优秀的解决方案,很适合处理此类问题,但也有一些细节需要注意,因此有了这篇文章,希望可以记录下来。

1.1 定义

  • 数据持有类

  • 感知组件生命周期

  • 数据能够被观察者所观察

1.2 使用 LiveData 的优势

  • 确保界面符合数据状态

  • 不会发生内存泄漏

  • 不会因 Activity 停止而导致崩溃

  • 不再需要手动处理生命周期

  • 数据始终保持最新状态

  • 适当的配置更改

  • 共享资源

2. 正文

2.1 使用 LiveData 步骤

2.1.1 创建 LiveData 实例以存储某种类型的数据。这通常在 ViewModel 类中完成。

     public class NameViewModel extends ViewModel {
        // Create a LiveData with a String        private MutableLiveData<String> currentName;
        public MutableLiveData<String> getCurrentName() {            if (currentName == null) {                currentName = new MutableLiveData<String>();            }            return currentName;        }
        // Rest of the ViewModel...    }
复制代码

2.1.2 创建可定义 onChanged() 方法的 Observer 对象,该方法可以控制当 LiveData 对象存储的数据更改时会发生什么。通常情况下,您可以在界面控制器(如 Activity 或 Fragment)中创建 Observer 对象。使用 observe() 方法将 Observer 对象附加到 LiveData 对象。observe() 方法会采用 LifecycleOwner 对象。这样会使 Observer 对象订阅 LiveData 对象,以使其收到有关更改的通知。通常情况下,您可以在界面控制器(如 Activity 或 Fragment)中附加 Observer 对象


    public class NameActivity extends AppCompatActivity {
        private NameViewModel model;
        @Override        protected void onCreate(Bundle savedInstanceState) {            super.onCreate(savedInstanceState);
            // Other code to setup the activity...
            // Get the ViewModel.            model = new ViewModelProvider(this).get(NameViewModel.class);
            // Create the observer which updates the UI.            final Observer<String> nameObserver = new Observer<String>() {                @Override                public void onChanged(@Nullable final String newName) {                    // Update the UI, in this case, a TextView.                    nameTextView.setText(newName);                }            };
            // Observe the LiveData, passing in this activity as the LifecycleOwner and the observer.            model.getCurrentName().observe(this, nameObserver);        }    }
复制代码

2.1.3 更新 LiveData 对象,LiveData 没有公开可用的方法来更新存储的数据。MutableLiveData 类将公开 setValue(T) 和 postValue(T) 方法,如果您需要修改存储在 LiveData 对象中的值,则必须使用这些方法。


    button.setOnClickListener(new OnClickListener() {        @Override        public void onClick(View v) {            String anotherName = "John Doe";            model.getCurrentName().setValue(anotherName);        }    });
复制代码

2.2 LiveData 代码分析

2.2.1 MutableLiveData.java(LiveData 的一个派生类,由于 LiveData 并未提供给外部更新数据的接口,所以一般使用 MutableLiveData 来实例化 LiveData)

package androidx.lifecycle;
/** * {@link LiveData} which publicly exposes {@link #setValue(T)} and {@link #postValue(T)} method. * * @param <T> The type of data hold by this instance */@SuppressWarnings("WeakerAccess")public class MutableLiveData<T> extends LiveData<T> {
    /**     * Creates a MutableLiveData initialized with the given {@code value}.     *     * @param value initial value     */    public MutableLiveData(T value) {        super(value);    }
    /**     * Creates a MutableLiveData with no value assigned to it.     */    public MutableLiveData() {        super();    }
    @Override    public void postValue(T value) {        super.postValue(value);    }
    @Override    public void setValue(T value) {        super.setValue(value);    }}
复制代码

2.2.2 LiveData.observe()方法

    @MainThread // 标记该方法只允许在主线程运行,一般是在Activity/Service的onCreate方法中执行     // 第一个参数 LifecycleOwner,表示的是一个具有生命周期的通用组件,如Activity/Service     // 第二个参数 Observer,就是我们的观察者实例,当数据变化时会执行onChange方法
    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); // 添加到组件的观察者队列    }
复制代码

2.2.3 注意事项:


    我们看一段注释,如果你已经 post 一个任务给主线程,但还未来得及执行,此时你再多次调用 postValue,则意味着最新的值会被 post,后面的值会覆盖前面的值。这一点需要特别注意,笔者在开发的时候,由于在 Service 中根据网络状态来更新 LiveData 的值,但是发现 Activity 中部分值无法观察到,后来看了注释才焕然大悟。


/**     * Posts a task to a main thread to set the given value. So if you have a following code     * executed in the main thread:     * <pre class="prettyprint">     * liveData.postValue("a");     * liveData.setValue("b");     * </pre>     * The value "b" would be set at first and later the main thread would override it with     * the value "a".     * <p>     * If you called this method multiple times before a main thread executed a posted task, only     * the last value would be dispatched.     *     * @param value The new value     */    protected void postValue(T value) {
复制代码

3. 总结

本文简单介绍了 JetPack 组件中的一个话题,但不仅仅于此,未完待续,敬请期待。


发布于: 2021 年 01 月 22 日阅读数: 464
用户头像

Changing Lin

关注

获得机遇的手段远超于固有常规之上~ 2020.04.29 加入

我能做的,就是调整好自己的精神状态,以最佳的面貌去面对那些未曾经历过得事情,对生活充满热情和希望。

评论

发布
暂无评论
[JetPack] LiveData源码解析