Jetpack之LiveData加ViewModle结合使用

一、LiveData介绍:

        首先来句简单的:观察监听了数据的变化,方便了很多通知操作。
        LiveData 是一种可观察的数据存储器类。与常规的可观察类不同,LiveData 具有生命周期感知能力,意指它遵循其他应用组件(如 Activity、Fragment 或 Service)的生命周期。这种感知能力可确保 LiveData 仅更新处于活跃生命周期状态的应用组件观察者。

二、LiveData优点

确保界面符合数据状态
        LiveData 遵循观察者模式。当底层数据发生变化时,LiveData 会通知 Observer 对象。您可以整合代码以在这些 Observer 对象中更新界面。这样一来,您无需在每次应用数据发生变化时更新界面,因为观察者会替您完成更新。
不会发生内存泄漏
        观察者会绑定到 Lifecycle 对象,并在其关联的生命周期遭到销毁后进行自我清理。
不会因 Activity 停止而导致崩溃
        如果观察者的生命周期处于非活跃状态(如返回堆栈中的 activity),它便不会接收任何 LiveData 事件。
不再需要手动处理生命周期
        界面组件只是观察相关数据,不会停止或恢复观察。LiveData 将自动管理所有这些操作,因为它在观察时可以感知相关的生命周期状态变化。
数据始终保持最新状态
        如果生命周期变为非活跃状态,它会在再次变为活跃状态时接收最新的数据。例如,曾经在后台的 Activity 会在返回前台后立即接收最新的数据。
适当的配置更改
        如果由于配置更改(如设备旋转)而重新创建了 activity 或 fragment,它会立即接收最新的可用数据。
共享资源
        您可以使用单例模式扩展 LiveData 对象以封装系统服务,以便在应用中共享它们。LiveData 对象连接到系统服务一次,然后需要相应资源的任何观察者只需观察 LiveData 对象。

三、直接代码举例说明,看看怎么用

1、简单的监听操作:

        通过点击屏幕按钮,改变后端ViewModel数据。通过LiveData监听数据更新UI
LiveDataView数据类

class LiveDataModel:ViewModel() {

    val currentNum: MutableLiveData<Int> by lazy {
        MutableLiveData<Int>(0)
    }

    val age: MutableLiveData<Int> by lazy {
        MutableLiveData<Int>(1)
    }
}

live_data_activity.xml布局页面

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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">

    <ImageButton
        android:id="@+id/imageButton2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:onClick="upOnclick"
        app:srcCompat="@drawable/ic_baseline_thumb_up_50" />

    <TextView
        android:id="@+id/text_view"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:textSize="30dp"
        android:text="0000"
        android:background="@color/white"/>

    <ImageButton
        android:id="@+id/imageButton"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:onClick="upDown"
        app:srcCompat="@drawable/ic_baseline_thumb_down_50" />

</LinearLayout>

LiveDataModelActivity

class LiveDataModelActivity : AppCompatActivity() {

    private val viewModel: LiveDataModel by viewModels()
    /*相当于
    private lateinit var viewModel: LiveDataModel
    viewModel = ViewModelProvider(this).get(LiveDataModel::class.java)*/

    private lateinit var viewBindingData: LiveDataActivityBinding

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        viewBindingData = LiveDataActivityBinding.inflate(layoutInflater)
        setContentView(viewBindingData.root)
        viewBindingData.textView.text = viewModel.currentNum.value.toString()  //将ViewModel的值进行赋值
        viewModel.currentNum.observe(this, Observer {
            viewBindingData.textView.text = it.toString()
        })
    }

    fun upOnclick(view: View) {
        viewModel.currentNum.postValue(viewModel.currentNum.value?.plus(1))
    }

    fun upDown(view: View) {
        viewModel.currentNum.postValue(viewModel.currentNum.value?.minus(1))
    }
}

效果
在这里插入图片描述

2、两个Fragment共同监听到数据的变化减少Fragment通信:

        两个Fragment界面都有一个seekBar通过LiveData监听。当拉动其中一个Fragment中seekBar,另一个Fragment中seekBar也跟着改变。
LiveDataModel

class LiveDataModel:ViewModel() {

    val currentNum: MutableLiveData<Int> by lazy {
        MutableLiveData<Int>(0)
    }

    val age: MutableLiveData<Int> by lazy {
        MutableLiveData<Int>(1)
    }
}

LiveDataModelFragment(第一个Fragment)

class LiveDataModelFragment : Fragment() {

    companion object {
        fun newInstance() = LiveDataModelFragment()
    }

    private lateinit var viewBindingData: FragmentLiveDataModelBinding
    private val viewModel: LiveDataModel by activityViewModels()

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View {
        viewBindingData = FragmentLiveDataModelBinding.inflate(inflater, container, false)
        viewModel.currentNum.observe(viewLifecycleOwner, Observer {
            viewBindingData.seekBar1.progress = it
        })

        viewBindingData.seekBar1.setOnSeekBarChangeListener(object : OnSeekBarChangeListener{
            override fun onProgressChanged(seekBar: SeekBar?, progress: Int, fromUser: Boolean) {
                viewModel.currentNum.value = progress
            }

            override fun onStartTrackingTouch(seekBar: SeekBar?) {
            }

            override fun onStopTrackingTouch(seekBar: SeekBar?) {
            }

        })
        return viewBindingData.root
    }
}

        注意:setValue只可以在主线程中调用。postValue可以在主线程或者子线程中调用,数据会从子线程派送到主线程更新,
        如果调用多次postValue更新数据,则在主线程执行更新前,LiveData的value只会保存最后一次的post值。
fragment_live_data_model.xml

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <SeekBar
        android:id="@+id/seekBar1"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>

</FrameLayout>

LiveDataModel2Fragment(第二个Fragment)

class LiveDataModel2Fragment : Fragment() {

    companion object {
        fun newInstance() = LiveDataModel2Fragment()
    }

    private val viewModel: LiveDataModel by activityViewModels()
    private lateinit var viewBinding : FragmentLiveDataModel2Binding

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View {
        viewBinding = FragmentLiveDataModel2Binding.inflate(inflater, container, false)
        viewModel.currentNum.observe(viewLifecycleOwner, Observer {
            viewBinding.seekBar2.progress = it
        })

        viewBinding.seekBar2.setOnSeekBarChangeListener(object : SeekBar.OnSeekBarChangeListener{
            override fun onProgressChanged(seekBar: SeekBar?, progress: Int, fromUser: Boolean) {
                viewModel.currentNum.value = progress
            }

            override fun onStartTrackingTouch(seekBar: SeekBar?) {
            }

            override fun onStopTrackingTouch(seekBar: SeekBar?) {
            }

        })
        return viewBinding.root
    }
}

fragment_live_data_model2.xml

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <SeekBar
        android:id="@+id/seekBar2"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>
</FrameLayout>

LiveDataModelActivity2

class LiveDataModelActivity2: AppCompatActivity(){

    private lateinit var viewBinding: LiveDataModelActivity2Binding

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        viewBinding = LiveDataModelActivity2Binding.inflate(layoutInflater)
        setContentView(viewBinding.root)
    }
}

live_data_model_activity2.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <androidx.fragment.app.FragmentContainerView
        android:id="@+id/fragment1"
        android:name="LiveDataModelFragment"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1" />


    <androidx.fragment.app.FragmentContainerView
        android:id="@+id/fragment2"
        android:name="LiveDataModel2Fragment"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"/>

</LinearLayout>

四、结尾:

        通常情况下LiveData都是配合viewModel使用,在某个具体的ViewModel类中定义LiveData数据,然后在对应的Activity或Fragment中观察LiveData数据的变化,LiveData的使用使得我们不再将数据保存在Activity或Fragment中,减轻了Activity或Fragment的工作量,使得Activity或Fragment只负责界面的管理和显示,而不在保存数据也不会受到数据的影响。
        下一篇文章讲介绍:ViewModel + LiveData + DataBinding的结合使用

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Android Jetpack是一组用于Android应用程序开发的库集合,旨在帮助开发者简化开发流程、提高生产力和应用性能。它提供了一些常用的组件和工具,可以帮助开发者解决常见的开发问题。 要使用Android Jetpack,您需要在您的项目中添相关的Jetpack库依赖。您可以通过在项目的build.gradle文件中添相应的依赖来实现。例如,要使用Navigation组件,您可以添以下依赖: implementation "androidx.navigation:navigation-fragment-ktx:2.3.5" implementation "androidx.navigation:navigation-ui-ktx:2.3.5" 一旦您添了所需的依赖,您可以开始使用Jetpack组件了。对于Navigation组件,您可以使用Navigation图形化界面来创建和管理应用程序中的导航结构,并使用NavController来处理导航操作。 另外,为了更好地理解和学习Android Jetpack,您可以借助官方文档和示例代码来深入学习。官方文档提供了详细的介绍和用法示例,而示例代码可以帮助您更好地理解如何在实际项目中应用Jetpack组件。 总结起来,要使用Android Jetpack,您需要添相关的库依赖,并根据具体的组件使用文档进行配置和使用。通过深入学习官方文档和示例代码,您可以更好地理解和掌握Jetpack使用。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *3* [Android Jetpack架构开发,从入门到实战,看这一篇就够了](https://blog.csdn.net/Eqiqi/article/details/127534594)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] - *2* [Android JetPack学习](https://blog.csdn.net/weixin_39069034/article/details/100170739)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值