IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 移动开发 -> Jetpack之LiveData加ViewModle结合使用 -> 正文阅读

[移动开发]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的结合使用

  移动开发 最新文章
Vue3装载axios和element-ui
android adb cmd
【xcode】Xcode常用快捷键与技巧
Android开发中的线程池使用
Java 和 Android 的 Base64
Android 测试文字编码格式
微信小程序支付
安卓权限记录
知乎之自动养号
【Android Jetpack】DataStore
上一篇文章      下一篇文章      查看所有文章
加:2022-09-13 11:27:25  更:2022-09-13 11:32:55 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/25 5:55:25-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码