LiveData从入门到实战

一、简介
1、什么是LiveData

LiveData 是一种可观察的数据存储器类。与常规的可观察类不同,LiveData 具有生命周期感知能力,意指它遵循其他应用组件(如 Activity、Fragment 或 Service)的生命周期。

2、LiveData 优势
  • 确保界面符合数据状态LiveData 遵循观察者模式。

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

  • 不会发生内存泄漏

观察者会绑定到 Lifecycle 对象,并在其关联的生命周期遭到销毁后进行自我清理。

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

如果观察者的生命周期处于非活跃状态(如返回栈中的 Activity),则它不会接收任何 LiveData 事件。

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

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

  • 数据始终保持最新状态

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

  • 适当的配置更改

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

  • 共享资源

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

二、代码实战
1、添加依赖
  • 项目build.gradle中
allprojects {
    repositories {
        google()
        jcenter()
    }
}
  • app模块下build.gradle中
def lifecycle_version = "2.2.0"
implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:$lifecycle_version"
implementation "androidx.lifecycle:lifecycle-livedata-ktx:$lifecycle_version"
2、创建LiveData对象
class UserViewModel : ViewModel() {

    val userBean = MutableLiveData<User>()
    fun requestUserData() {
        // 协程模拟耗时100ms
        runBlocking {
            delay(100)
            userBean.value = User("张三", 18)
        }
    }
}

data class User(var name: String, var age: Int)
3、转换LiveData
  • 通过Transformations.map进行转换
  • map操作 对存储在 LiveData 对象中的值应用函数,并将结果传播到下游
        val mNameAll = MutableLiveData<String>()
        // 设置数据
        mNameAll.postValue("张三")

        val mTransformMap = Transformations.map(mNameAll) { nameAll ->
            "$nameAll, 李四"
        }

        mTransformMap.observe(this) {
            Log.d("tag", "mMapData $it")
            // D/tag: mMapData 张三, 李四
        }

  • 通过Transformations.switchMap进行装换
  • switchMap 将结果解封和分派到下游。传递给 switchMap() 的函数必须返回 LiveData 对象
        val mMapUser = MutableLiveData<User>()
        val mSwitchMapUser = MutableLiveData<User>()
        val mIsMap = MutableLiveData<Boolean>()
        val mSwitchMapData = Transformations.switchMap(mIsMap) { mIsMap ->
            if (mIsMap) {
                mMapUser.postValue(mUser.value)
                mMapUser
            } else {
                mSwitchMapUser
            }
        }

        mSwitchMapData.observe(this) {
            Log.d("tag", "mSwitchMapData ${it.name}   ${it.age}")
            // D/tag: mSwitchMapData 李四   24
        }
        // switchMap
        btnSwitchMap.setOnClickListener {
            mSwitchMapUser.postValue(User("李四", 24))
            mIsMap.postValue(false)
        }
4、数据合并MediatorLiveData
    val mNameOne = MutableLiveData<String>()
    val mNameTwo = MutableLiveData<String>()
    val mediatorLiveData = MediatorLiveData<String>()
    // 依次给mNameOne和mNameTwo设置值
    mNameOne.postValue("张三")
    mNameTwo.postValue("李四")

    mediatorLiveData.addSource(mNameOne) {
    Log.d("tag", "mNameOne $it")
    //  D/tag: mNameOne 张三
    mediatorLiveData.value = it
    }
    mediatorLiveData.addSource(mNameTwo) {
    Log.d("tag", "mNameTwo $it")
    // D/tag: mNameTwo 李四
    mediatorLiveData.value = it
    }
    mediatorLiveData.observe(this) {
    Log.d("tag", "mediatorLiveData  is $it")
    }
  • 打印日志如下:
// D/tag: mNameOne 张三
// D/tag: mediatorLiveData  is 张三
// D/tag: mNameTwo 李四
// D/tag: mediatorLiveData  is 李四

通过日志可以看到,因为mNameOne和mNameTwo作为mediatorLiveData的source,
mediatorLiveData可以监听到两者的值

5、Activity中使用
class LiveDataDemoActivity : AppCompatActivity() {

    private lateinit var userViewModel: UserViewModel

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_live_data_demo)
        // initViewModel
        userViewModel = ViewModelProviders.of(this).get(UserViewModel::class.java)

        initListener()
        initData()
    }

    private fun initListener() {
        getUserData.setOnClickListener {
            userViewModel.requestUserData()
        }
        // 修改数据
        btnChange.setOnClickListener {
            userViewModel.userBean.postValue(User(name = "李四", age = 24))
        }
    }

    private fun initData() {
        userViewModel.userBean.observe(this, Observer {
            tvUserInfo.text = "名字是:${it.name},年龄是:${it.age}"

        })

    }
}
6、布局文件
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

    <TextView
            android:id="@+id/user"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="用户:"
            android:textColor="@android:color/black"
            android:textSize="16sp"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent" />

    <TextView
            android:id="@+id/tvUserInfo"
            android:layout_width="wrap_content"
            android:layout_height="20dp"
            android:text="小明"
            android:textColor="@android:color/black"
            android:textSize="16sp"
            app:layout_constraintStart_toEndOf="@+id/user"
            app:layout_constraintTop_toTopOf="parent" />

    <Button
            android:id="@+id/btnChange"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginBottom="20dp"
            android:text="修改用户数据"
            app:layout_constraintBottom_toTopOf="@+id/getUserData" />

    <Button
            android:id="@+id/getUserData"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:gravity="center"
            android:text="获取用户数据"
            app:layout_constraintBottom_toBottomOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
三、参考
  • https://developer.android.google.cn/topic/libraries/architecture/livedata?hl=zh_cn
  • https://www.itranslater.com/qa/details/2583127127965041664
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值