• Android Jetpack系列(五):LiveData(使用篇)


    LiveData概述

    LiveData 是一种可观察的数据存储器类: 与常规的可观察类不同,LiveData 具有生命周期感知能力,意指它遵循其他应用组件(如 Activity、Fragment 或 Service)的生命周期;这种感知能力可确保 LiveData 仅更新处于活跃生命周期状态的应用组件观察者

    如果观察者(由 Observer 类表示)的生命周期处于 STARTED 或 RESUMED 状态,则 LiveData 会认为该观察者处于活跃状态; LiveData 只会将更新通知给活跃的观察者,为观察 LiveData 对象而注册的非活跃观察者不会收到更改通知

    你可以注册与实现 LifecycleOwner 接口的对象配对的观察者; 有了这种关系,当相应的 Lifecycle 对象的状态变为 DESTROYED 时,便可移除此观察者;这对于 Activity 和 Fragment 特别有用,因为它们可以放心地观察 LiveData 对象而不必担心泄露(当 Activity 和 Fragment 的生命周期被销毁时,系统会立即退订它们)

    LiveData优势

    LiveData 遵循观察者模式; 当生命周期状态发生变化时,LiveData 会通知 Observer 对象。您可以整合代码以在这些 Observer 对象中更新界面。观察者可以在每次发生更改时更新界面,而不是在每次应用数据发生更改时更新界面

    不会发生内存泄露
    观察者会绑定到 Lifecycle 对象,并在其关联的生命周期遭到销毁后进行自我清理
    不会因 Activity 停止而导致崩溃
    如果观察者的生命周期处于非活跃状态(如返回栈中的 Activity),则它不会接收任何 LiveData 事件
    不再需要手动处理生命周期
    界面组件只是观察相关数据,不会停止或恢复观察。LiveData 将自动管理所有这些操作,因为它在观察时可以感知相关的生命周期状态变化
    数据始终保持最新状态
    如果生命周期变为非活跃状态,它会在再次变为活跃状态时接收最新的数据。例如,曾经在后台的 Activity 会在返回前台后立即接收最新的数据
    适当的配置更改
    如果由于配置更改(如设备旋转)而重新创建了 Activity 或 Fragment,它会立即接收最新的可用数据

    共享资源

    您可以使用单例模式扩展 LiveData 对象以封装系统服务,以便在应用中共享它们; LiveData 对象连接到系统服务一次,然后需要相应资源的任何观察者只需观察 LiveData 对象

    LiveData使用

    首先需要引入LiveData库, 因为依赖有传递作用,所以我们依赖下面这一个就可以了

    	implementation "androidx.lifecycle:lifecycle-extensions:2.2.0"
    
    
    • 1
    • 2

    LiveData一般情况下要结合ViewModel使用,ViewModel后面会单独篇幅介绍,这里为了演示方便就直接在Activity中使用LiveData了

    1 LiveData基本使用

    class TestActivity : AppCompatActivity() {
    
        private val TAG by lazy {
            TestActivity::class.java.simpleName
        }
    
        private val data = MutableLiveData<String>()
    
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContentView(R.layout.activity_main)
            data.observe(this, Observer {
                Log.i(TAG, "value: ${lifecycle.currentState} + $it ")
            })
        }
    
        fun onTest(view: View) {
            data.postValue("LiveData")
        }
        //打印信息
        TestActivity: value: LiveData 
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    LiveData是一个抽象类,MutableLiveData是它的实现类; 首先声明一个MutableLiveData对象,然后调用data.observer(lifecycleOwner, observer), 第一个参数是lifecycleOwner, 在Lifecycle原理篇中详细提到它,它是和生命周期紧密相关的一个类,这里也就是将LiveData组件和生命周期绑定,第二个参数是一个回调,当有数据更新的时候会调用它。然后当点击按钮执行onTest方法的时候,就会更新MutableLiveData数值,导致回调被调用,模拟数据更新

    2 Transformations.map()

    class TestActivity : AppCompatActivity() {
    
       private val data = MutableLiveData<String>()
    
       override fun onCreate(savedInstanceState: Bundle?) {
           super.onCreate(savedInstanceState)
           setContentView(R.layout.activity_main)
    
           data.observe(this, Observer {
               Log.d(TAG, "Changed1:$it")
           })
    
           val transformedLiveData: LiveData<String> = Transformations.map(data) {
               "$it+map"
           }
           transformedLiveData.observe(this, Observer {
               Log.d(TAG, "Changed2:$it")
           })
       }
    
       fun onTest(view: View) {
           data.postValue("LiveData")
       }
    }
    //打印如下
    TestActivityChanged1:LiveData
    TestActivityChanged2:LiveData+map
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 上述代码使用Transformations.map(data)LiveData中存储的值做了更改,并最终被观察者回调打印

    3 Transformations.switchMap()

    class TestActivity : AppCompatActivity() {
        private lateinit var data1: MutableLiveData<String>
        private lateinit var data2: MutableLiveData<String>
        private lateinit var switchData: MutableLiveData<Boolean>
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContentView(R.layout.activity_main)
            data1 = MutableLiveData()
            data2 = MutableLiveData()
            switchData = MutableLiveData()
            val transformedLiveData: LiveData<String> = Transformations.switchMap(switchData) {
                if (it) {
                    Log.i(TAG, "----------true---data1--")
                    data1
                } else {
                    Log.i(TAG, "----------false---data2--")
                    data2
                }
            }
            transformedLiveData.observe(this, Observer {
                Log.d(TAG, "onChanged:$it")
            })
        }
    
        fun onTest(view: View) {
            switchData.postValue(true)
            data1.postValue("data1")
            data2.postValue("data2")
        }
    	//打印信息如下
    	TestActivity: ----------true---data1--
    	TestActivity: onChanged:data1
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34

    Transformations.switchMap()和Transformations.map()很相似,它可以根据需要自由的切换监听,和Transformations.map()的差别在于其方法内部需要返回一个LiveData对象

    4 MediatorLiveData.addSource()合并数据

    class TestActivity : AppCompatActivity() {
    
        private val data1 = MutableLiveData<String>()
        private val data2 = MutableLiveData<String>()
        private val mediatorLiveData = MediatorLiveData<String>()
    
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContentView(R.layout.activity_main)
    
            mediatorLiveData.addSource(data1) {
                Log.d(TAG, "onChanged1:$it")
                mediatorLiveData.value = it
            }
            mediatorLiveData.addSource(data2) {
                Log.d(TAG, "onChanged2:$it")
                mediatorLiveData.value = it
            }
            mediatorLiveData.observe(this, Observer {
                Log.d(TAG, "onChanged:$it")
            })
        }
    
        fun onTest(view: View) {
            data1.postValue("data1")
        }
        //打印信息如下
        TestActivity:onChanged1:data1
    	TestActivity:onChanged:data1
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31

    mediatorLiveData.addSource添加了两个LiveData对象,它内部可以存储多个LiveData数据集,监听多个数据的变化,如当点击执行onTest时候data1数据发生变化时候,会监听到变化的结果,同理如果data2数据源发生变化的时候,也会被监听到

    以上就是今天的所有内容,相信大家看完之后都会有着自己的收获,但是盲目的学习并不能让你的技术稳定的增长

    我自荐一套 《完整的Android学习资料,以及一些视频课讲解》

    现在私信发送 “进阶” 即可免费获取

    学习没有捷径可言,我们要注意记学习,不仅要记,还要写心得体会,文字笔记、画图、总结等,方式很多,但是一定要自己认真去做,不要太相信自己的记忆,只有反复记忆,加深理解才行

    同时,对于程序员而言,不单单是死记硬背,我们有更好的方式去学习,比如写demo去验证。复习知识点时,要及时跟你做过的项目结合起来,这样在面试时就知道怎么聊了,由项目讲到知识点,由一个知识点串联到另一个知识点。复习到一定阶段,可以尝试着去把这些东西串联起来,由点及面,形成知识体系

    最后我想说:

    对于程序员来说,要学习的知识内容、技术有太多太多,要想不被环境淘汰就只有不断提升自己,从来都是我们去适应环境,而不是环境来适应我们

    技术是无止境的,你需要对自己提交的每一行代码、使用的每一个工具负责,不断挖掘其底层原理,才能使自己的技术升华到更高的层面

    Android 架构师之路还很漫长,与君共勉

  • 相关阅读:
    力扣labuladong——一刷day03
    软件测试中的测试工具和自动化测试
    智能聊天机器人的优势在哪里?资深独立站卖家告诉你!
    jvm类加载过程
    elf文件与链接脚本
    C++ Reference: Standard C++ Library reference: C Library: ctime: difftime
    Python二手房价格预测(二)——数据处理及数据可视化
    Java-学生选课系统
    MySQL尾部空格处理与哪些设置有关? 字符集PAD SPACE与NO PAD属性的区别、MySQL字段尾部有空格为什么也能查询出来?
    尚硅谷SpringMVC (9-13)
  • 原文地址:https://blog.csdn.net/m0_70748845/article/details/126089347