我是靠谱客的博主 正直信封,最近开发中收集的这篇文章主要介绍Android Jetpack架构组件——LiveData使用篇,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

概述

一般来说,LiveData很少单独使用,它更多的和Android Jetpack的其他组件搭配使用,比如ViewModel和ViewBinding。所以前面我们介绍ViewModel的使用以及其实现原理。那么这篇文章就来介绍LiveData的使用。

LiveData是什么?

通过字面意思其实我们可以理解成生存(活着)的数据。我们看下官方是怎么介绍它的:

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

化繁为简:

  • LiveData具备生命周期的感知能力
  • LiveData只存在活跃的生命周期里,比如STARTED或RESUMED。

LiveData的优势

使用 LiveData 具有以下优势:

  • 确保界面符合数据状态
    LiveData 遵循观察者模式。当底层数据发生变化时,LiveData会通知Observer对象。您可以整合代码以在这些Observer对象中更新界面。这样一来,您无需在每次应用数据发生变化时更新界面,因为观察者会替您完成更新。

  • 不会发生内存泄漏
    观察者会绑定到 Lifecycle 对象,并在其关联的生命周期遭到销毁后进行自我清理。
    不会因 Activity 停止而导致崩溃如果观察者的生命周期处于非活跃状态(如返回栈中的 Activity),则它不会接收任何LiveData事件。

  • 不再需要手动处理生命周期
    界面组件只是观察相关数据,不会停止或恢复观察。LiveData将自动管理所有这些操作,因为它在观察时可以感知相关的生命周期状态变化。

  • 数据始终保持最新状态
    如果生命周期变为非活跃状态,它会在再次变为活跃状态时接收最新的数据。例如,曾经在后台的Activity会在返回前台后立即接收最新的数据。

  • 适当的配置更改
    如果由于配置更改(如设备旋转)而重新创建了Activity或Fragment,它会立即接收最新的可用数据。

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

如何使用LiveData

前面我们介绍了LiveData是什么以及它的优势有什么,那么接下来我们介绍下到底如何使用它。

基本使用

LiveData是一个抽象类,不能直接使用,我们一般使用它的直接子类MutableLiveData。那我们直接写例子,直接在之前的ViewModel里面修改代码:

/**
 * @date:2021/2/22
 * @author:Silence
 * @describe:
 **/
class MyViewModel : ViewModel() {

    var userData: MutableLiveData<UserInfo> = MutableLiveData()

    fun getUserInfo() {
        val user = UserInfo("我就是马云飞", (1..100).random())
        userData.postValue(user)
    }

    fun updateUserInfo(userInfo: UserInfo) {
        userData.postValue(userInfo)
    }
}

然后我们看看怎么在Activity里面获取这个data呢。接着看代码:

    private val viewModel by lazy { ViewModelProvider(this).get(MyViewModel::class.java) }
    private var count = 0
    
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_view_model)
        viewModel.userData.observe(this, Observer {
            Log.i(TAG, "onCreate: " + "姓名:${it.name} t年龄:${it.age}")
        })
        liveDataBtn.setOnClickListener {
            if (count % 2 == 0) {
                viewModel.getUserInfo()
            } else {
                val user = UserInfo("你不是马云飞", (1..100).random())
                viewModel.updateUserInfo(user)
            }
            count++
        }
    }

我们在Activity中对viewModel的userData做了监听,实时观察数据的变化。那么我们现在进行点击看看效果如何:

image

果然,只要我数据更新了,我的Log立马就输出了。

扩展使用

如果观察者的生命周期处于STARTED或RESUMED状态,则LiveData会认为该观察者处于活跃状态。我们直接看官方的例子:

class StockLiveData(symbol: String) : LiveData<BigDecimal>() {
    //股票管理类
    private val stockManager: StockManager = StockManager(symbol)

    //监听股票价格的变化
    private val listener = { price: BigDecimal ->
        //更新value值
        value = price
    }

    //页面处于活跃状态时,开始观察股票价格的数据更新
    override fun onActive() {
        stockManager.requestPriceUpdates(listener)
    }

    //页面处于非活跃状态,移除相关监听
    override fun onInactive() {
        stockManager.removeUpdates(listener)
    }

    companion object {
        private lateinit var sInstance: StockLiveData

        //这是一个单例
        @MainThread
        fun get(symbol: String): StockLiveData {
            sInstance = if (::sInstance.isInitialized) sInstance else StockLiveData(symbol)
            return sInstance
        }
    }
}

//Fragment中的使用
class MyFragment : Fragment() {

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        StockLiveData.get(symbol).observe(viewLifecycleOwner, Observer<BigDecimal> { price: BigDecimal? ->
            // Update the UI.
        })

    }

我们看下上述的代码,具体包含如下功能:

  • 本身是个单例,也就是可以在多个Activity与Fragment中进行数据监听。

  • 当具备活跃的观察者时,会调用onActive方法,监听股价的变动。

  • 当其观察者不具备活跃状态时,会调用onInactive方法,移除监听。也就是就算值改变了,也不会同步更新,同理,当页面销毁时,会自动移除监听。

数据转换

map

我们按照上面我们的示例代码继续,前面我们打印了姓名和年龄,那么假设,我暂时不需要字段,我需要通过姓名拿到他的班级以及学号。也就是通过姓名将数据转换成班级和学号,LiveData也给我们提供了相关方法,可以通过Transformations.map去实现。具体代码如下:

// ViewModelActivity.kt
override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_view_model)
        viewModel.userData.observe(this, Observer {
            Log.i(TAG, "onCreate: " + "姓名:${it.name} t年龄:${it.age}")
        })
        viewModel.getUserInfo()
        viewModel.classInfo.observe(this, Observer {
            Log.i(TAG, "onCreate: " + "班级:${it?.grade} t学号:${it?.id}")
        })
        liveDataBtn.setOnClickListener {
            viewModel.getClassIdByUser().observe(this, Observer {
            })
        }
    }

// MyViewModel.kt
fun getClassIdByUser(): LiveData<ClassBean?> {
        return Transformations.map(userData) { input ->
            var classBean: ClassBean? = null
            if (input?.name == "我就是马云飞") {
                classBean = ClassBean("高三", (1..100).random())
                classInfo.postValue(classBean)
            }
            classBean
        }
    }

首先我们进入页面先获取一次用户的姓名和年龄,然后当我们点击按钮的时候,我们根据用户的姓名给他定义一个班级和学号。我们来看下效果:

可以看到,每次点击的时候,它都会给我们生成一个学号。说明我们的数据转换成功了。

switchMap

switchMap的方法和map大同小异,只是它是返回一个liveData,而上面map是直接返回T。我们直接上代码:

 fun getClassIdByUser(): LiveData<ClassBean?> {
        return Transformations.switchMap(userData) {
            val classBean = ClassBean("高三", (1..100).random())
            classInfo.postValue(classBean)
            classInfo
        }
    }

输出也基本差不多。

数据合并

所谓的数据合并是什么呢?之前我们如果有多套的LiveData,我们需要对多套数据进行观察。而数据合并可以做到批量添加LiveData并且只实现一组观察逻辑就可以监听多套数据的改动。我们修改一下代码:

        viewModel.mediatorLiveData.addSource(viewModel.userData) {
            Log.i(TAG, "卧槽,数据合并也可以监听!!!!onCreate: " + "姓名:${it.name} t年龄:${it.age}")
        }
        viewModel.mediatorLiveData.addSource(viewModel.classInfo) {
            Log.i(TAG, "卧槽,数据合并也可以监听!!!!onCreate: " + "班级:${it?.grade} t学号:${it?.id}")
        }
        viewModel.mediatorLiveData.observe(this, Observer<Any?> {
        })
        liveDataBtn.setOnClickListener {
            if (count % 2 == 0) {
                viewModel.getUserInfo()
            } else {
                viewModel.getClassInfo()
            }
            count++
        }

我们继续通过点击看看效果如何:

哎。可以了~

总结

本文我们主要介绍了LiveData是什么,以及它的优势和使用方法。而LiveData的很多细节我们没有去关注,比如postValue和setValue。比如Transformations的map和switchMap方法。后面我们会在LiveData原理篇讲到。毕竟我们需要了解它是怎么使用的。会使用后才会想去了解其原理。

参考

官网

本文首发于我的个人博客:Android Jetpack架构组件——LiveData使用篇

更多文章请关注我的公众号:码农职场

在这里插入图片描述

最后

以上就是正直信封为你收集整理的Android Jetpack架构组件——LiveData使用篇的全部内容,希望文章能够帮你解决Android Jetpack架构组件——LiveData使用篇所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(68)

评论列表共有 0 条评论

立即
投稿
返回
顶部