美文网首页
Android Jetpack — LiveData

Android Jetpack — LiveData

作者: 安静的蓝孩子 | 来源:发表于2020-06-16 17:24 被阅读0次

    LiveData 是一种具有感知应用组件(ActivityFragmentService)生命周期的,可观察的数据存储器类。这种感知能力可确保LiveData仅更新处于活跃生命周期状态的应用组件观察者。(官网解释)

    LiveData的使用

    先附上一张demo效果图

    图1

    在使用LiveData前,需要先添加依赖。

    LiveData 的依赖,可以查看官方文档,导入最新的版本。

    官网地址

    现在示例使用的版本:

    def lifecycle_version = "2.2.0"
    // ViewModel
    implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:$lifecycle_version"
    // LiveData
    implementation "androidx.lifecycle:lifecycle-livedata-ktx:$lifecycle_version"
    

    创建 LivaData 对象

    LiveData是一个数据的封装容器,可以存放包括实现了Collection的对象,如List
    LiveData对象通常存储在ViewModel中,可以通过getter进行访问,通过setter修改(异步需要用postValue)。

    ViewModel 可以参考上一篇文章,Android Jetpack — ViewModel

    class NumberViewModel : ViewModel() {
    
        val num: MutableLiveData<Int> by lazy {
            MutableLiveData<Int>(0)
        }
    
    }
    

    添加 LivaData 监听

    //获取ViewModel
    mViewModel = ViewModelProvider(this).get(NumberViewModel::class.java)
        
    //新建一个观察者    
    val numObserver = Observer<Int> { num ->
        mTvNum.text = num.toString()
    }
    
    //开始监听
    mViewModel.num.observe(this, numObserver)
    

    监听时机:通常是在ActivityFragmentoncreate中,这样的好处是当组件处于STARTED状态时,就能接收到LiveData对象的最新数据。同时,也能确保在onResult中的重复调用。

    接收到数据更新的时机:

    1. 数据发生更改
    2. 观察者从非活跃状态更改为活跃状态
    3. 观察者第二次从非活跃状态更改为活跃状态,只有在自上次变为活跃状态以来数据发生了更改时,才会收到更新

    注意:如果LiveData对象num中设置了初始值,则在调用了observe()后,会立即掉用onChange(); 如果未设置初始值,则不会调用。

    更新数据

    mBtnAdd.setOnClickListener {
        //java mViewModel.num.setValue(mViewModel.num.value as Int + 1)
        mViewModel.num.value = mViewModel.num.value as Int + 1
    }
    

    更新LiveData数据需要调用MutableLiveData类的setValue(T)或者postValue(T)方法,LiveData类的这两个方法是不公开的。

    setValue(T)postValue(T)两者是有区别的:
    setValue(T)只能在主线程调用,而postValue(T)可以在子线程调用。

    /**
         * 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) {
            boolean postTask;
            synchronized (mDataLock) {
                postTask = mPendingData == NOT_SET;
                mPendingData = value;
            }
            if (!postTask) {
                return;
            }
            ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable);
        }
    
        /**
         * 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");
            mVersion++;
            mData = value;
            dispatchingValue(null);
        }
    

    通过源码可以看出,当调用postValue之后,会把任务抛到主线程中去执行,而setValue是直接执行。

    需要注意的是,如果在主线程中执行以下代码:

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

    会先把value设置为b,然后a覆盖b的值。

    扩展

    liveData还可以和Room、协程等一起使用,还有很多高级的用法,后续继续记录。

    相关文章

      网友评论

          本文标题:Android Jetpack — LiveData

          本文链接:https://www.haomeiwen.com/subject/gourxktx.html