js css html

JetPack<第二篇>:LiveData & ViewMode

2022-08-08  本文已影响0人  NoBugException

LiveData
1、定义:可观察的数据持有对象
2、优点:
(1)自动更新UI
(2)无内存泄漏
(3)不会引起程序崩溃
(4)无需手动处理生命周期
(5)共享资源 -- 需要继承LiveData并且实现单例
ViewModel
1、定义:用来处理跟UI相关的数据的类
2、优点:
(1)设备信息发生变更数据不会消失
(2)同一个Activity之间的Fragment可以实现数据共享 -- 使用Fragment中的activity提供ViewModel

1、添加依赖

ext.lifecycleVersion = '2.2.0-alpha01'
dependencies {
    // liveData
    implementation "androidx.lifecycle:lifecycle-livedata-ktx:$rootProject.lifecycleVersion"
    // viewModel
    implementation "androidx.lifecycle:lifecycle-viewmodel- ktx:$rootProject.lifecycleVersion"
    implementation "androidx.lifecycle:lifecycle-extensions:$rootProject.lifecycleVersion"
}

2、简单实现

【1】创建ViewModel,并在ViewModel创建MutableLiveData

class UserModel(application: Application) : AndroidViewModel(application) {

    val userLiveData = MutableLiveData<User>() // 创建 LiveData 对象
    private var mApplication: Application? = null

    init {
        userLiveData.postValue(User("张三", 2)) // 通知数据变化了
        mApplication = application
    }

    /**
     * 更新用户信息
     */
    fun updateUserInfo() {
        val user = userLiveData.value?.apply {
            userName = "张三"
            age = (1..100).random()
        }
        userLiveData.value = user // 或改成 userLiveData.postValue(user)

    }
}

【2】User类

data class User(var userName: String, var age: Int)

【3】ViewModelProvider

    val userModel = ViewModelProvider(this@LiveDataActivity).get(UserModel::class.java)

【4】使用 observe 或 observeForever 绑定观察者

    // 使用 observe 会让观察者随着生命周期的活跃而活跃,当生命周期处于活跃状态时LiveData才会更新数据,反之不会更新数据
    // 不需要主动调用 removeObserver(Observer) 移除观察者
    userModel.userLiveData.observe(this@LiveDataActivity, Observer<User> {
        binding.userinfo.text = "大家好,我叫" + it.userName + ",今年" + it.age + "岁了!"
    })

    // 使用 observeForever,会导致观察者一直处于活跃状态
    // 我们需要主动调用 removeObserver(Observer) 移除观察者
    userModel.userLiveData.observeForever {
        binding.userinfo.text = "大家好,我叫" + it.userName + ",今年" + it.age + "岁了!"
    }

【5】触发数据变化

    binding.activityDataButton.setOnClickListener {
         userModel.updateUserInfo()
    }

3、map 和 switchMap

    // 使用map函数,将User类型转成Int类型,Observer的返回值也从User类型转换成Int类型
    // Function 第一个参数表示输入,第二个参数表示输出
    // map 第一个参数表示输入数据,第二个参数Function的返回值是输出数据
    Transformations.map(userModel.userLiveData, Function<User, Int> {
        it.age
    }).observe(this@LiveDataActivity, Observer<Int> {
        binding.userinfo1.text = "大家好,我今年 $it 岁了!"
    })


    // 使用switchMap函数,将User类型转成LiveData<Int>类型,Observer的返回值从User类型转换成Int类型
    // Function 第一个参数表示输入,第二个参数表示输出
    // map 第一个参数表示输入数据,第二个参数Function的返回值是输出数据
    Transformations.switchMap(userModel.userLiveData, Function<User, LiveData<Int>> {
        val userLiveData = MutableLiveData<Int>()
        val age = userModel.userLiveData.value?.age
        userLiveData.postValue(age)
        userLiveData
    }).observe(this@LiveDataActivity, Observer<Int> {
        binding.userinfo.text = "大家好,我今年 $it 岁了!"
    })

其它步骤和 【2】 保持一致。

4、使用 MediatorLiveData 统一管理多个LiveData

【1】创建ViewModel,并在ViewModel创建MediatorLiveData和MutableLiveData

class UserModelByMediator(application: Application) : AndroidViewModel(application) {

    var mediatorLiveData: MediatorLiveData<User> = MediatorLiveData() // 创建 LiveData 集合对象,管理多个LiveData
    val userLiveData1 = MutableLiveData<User>() // 创建 LiveData 对象1
    val userLiveData2 = MutableLiveData<User>() // 创建 LiveData 对象2
    private var mApplication: Application? = null

    init {
        mediatorLiveData.addSource(userLiveData1) {
            mediatorLiveData.value = it
        }
        mediatorLiveData.addSource(userLiveData2) {
            mediatorLiveData.value = it
        }
        userLiveData1.postValue(User("张三", 2)) // 通知数据变化了
        userLiveData2.postValue(User("李四", 3)) // 通知数据变化了
        mApplication = application
    }

    /**
     * 更新用户信息1
     */
    fun updateUserInfo1() {
        val user = userLiveData1.value?.apply {
            userName = "张三"
            age = (1..100).random()
        }
        userLiveData1.value = user // 或改成 userLiveData1.postValue(user)
    }

    /**
     * 更新用户信息1
     */
    fun updateUserInfo2() {
        val user = userLiveData2.value?.apply {
            userName = "李四"
            age = (1..100).random()
        }
        userLiveData2.value = user // 或改成 userLiveData2.postValue(user)
    }
}

【2】user类

和上面一致

【3】ViewModelProvider

val userModelByMediator = ViewModelProvider(this@LiveDataActivity).get(UserModelByMediator::class.java)

【4】绑定观察者

    userModelByMediator.mediatorLiveData.observe(this@LiveDataActivity) {
        when(it.userName) {
            "张三" -> binding.userinfo1.text = "大家好,我叫${it.userName},今年${it.age}岁了!"
            "李四" -> binding.userinfo2.text = "大家好,我叫${it.userName},今年${it.age}岁了!"
        }
    }

【5】触发数据变化

    binding.activityDataButton.setOnClickListener {
        userModelByMediator.updateUserInfo1()
        userModelByMediator.updateUserInfo2()
    }

5、LiveData的单例实现

【1】创建一个单例

class UserLiveData : LiveData<User>() {
    companion object {

        private lateinit var mInstance: UserLiveData

        @JvmStatic
        @MainThread
        fun get(): UserLiveData {
            mInstance = if (::mInstance.isInitialized) {
                mInstance
            } else {
                UserLiveData()
            }
            return mInstance
        }
    }

    override fun onActive() {
        super.onActive()
    }

    override fun onInactive() {
        super.onInactive()
    }

    /**
     * 更新数据
     */
    fun updateUserInfo() {
        var user = get().value
        if (user == null) {
            user = User("", 0)
        }
        user.apply {
            userName = "张三"
            age = (1..100).random()
        }
        value = user // 或者 将 value = user 改成 postValue(user)
    }
}

onActive 和 onInactive 两个方法很重要
onActive:Activity 激活时执行
onInactive:Activity 挂起时执行

【2】绑定观察者

    // LiveData单例实现方式
    UserLiveData.get().observe(this@LiveDataActivity) {
        binding.userinfo1.text = "大家好,我叫" + it.userName + ",今年" + it.age + "岁了!"
    }

【3】触发数据更新

    binding.activityDataButton.setOnClickListener {
        UserLiveData.get().updateUserInfo()
    }

6、ViewModelProvider.Factory使用

没有使用 ViewModelProvider.Factory 的代码:

val userModel = ViewModelProvider(this@LiveDataActivity).get(UserModel::class.java)

使用  ViewModelProvider.Factory 的代码:

val userModel = ViewModelProvider(this@LiveDataActivity, UserModelFactory(application)).get(UserModel::class.java)

不使用 ViewModelProvider.Factory 的两种情况:
【1】当 Model 继承 AndroidViewModel 时,并且 Model 只有 Application 参数时:
class UserModel(application: Application) : AndroidViewModel(application)
【2】当 Model 继承 ViewModel,并且 ViewModel 没有参数时:
class UserModel : ViewModel()

使用 ViewModelProvider.Factory 的情况:
【1】当 Model 继承 AndroidViewModel 时,并且 Model 有除了 Application 参数之外还有其它参数时:
class UserModel(application: Application, age: Int) : AndroidViewModel(application)

class UserModelFactory(private val application: Application) : ViewModelProvider.Factory {
    @Suppress("UNCHECKED_CAST")
    override fun <T : ViewModel> create(modelClass: Class<T>): T {
        if (modelClass.isAssignableFrom(UserModel::class.java)) {
            return UserModel(application, 3) as T
        }
        throw IllegalArgumentException("Unknown ViewModel class")
    }
}

【2】当 Model 继承 ViewModel,并且 Model 有参数时:
val userModel = ViewModelProvider(this@LiveDataActivity, UserModelFactory(application)).get(UserModel::class.java)

class UserModelFactory(private val application: Application) : ViewModelProvider.Factory {
    @Suppress("UNCHECKED_CAST")
    override fun <T : ViewModel> create(modelClass: Class<T>): T {
        if (modelClass.isAssignableFrom(UserModel::class.java)) {
            return UserModel(application) as T
        }
        throw IllegalArgumentException("Unknown ViewModel class")
    }
}

[本章完...]

上一篇下一篇

猜你喜欢

热点阅读