zoukankan      html  css  js  c++  java
  • Jetpack系列:LiveData入门级使用方法

    Android APP开发中,开发者们都想有一个公共的组件,可以实现后台数据的监听,同时实时更新到UI进行显示,从而大大简化开发过程。Google针对这一开发需求,提供了Jetpack LiveData组件。下面我们来一起看下LiveData的基本使用方法吧!

    首先,先了解下使用LiveData的优点。

    • 确保UI与数据状态匹配

    • 不需要担心内存泄漏问题

    • Activity停止后数据变化不会导致Crash

    • 不再需要人工生命周期的处理

    • 始终使用最新的数据

    • 正确应用配置更改

    • 共享资源

    LiveData遵循观察者模式,实现LifeCycle接口,因此可以监听数据的实时更新,感知应用的生命周期,让开发者能够更多的关注业务具体实现。

    下面我们来通过一个小Demo来简单介绍下LiveData的基本使用方法。


    ![file](https://img2018.cnblogs.com/blog/1820853/201909/1820853-20190930133422041-186307834.gif)


    本例中,数据变化通知UI的显示由四个控件体现,分别为:系统时间(Long型)、系统时间、天气、远端数据。针对这四个控件的动态显示,我们分别来看下其是如何实现的。

    框架搭建


    APP首先需要搭建使用LiveData的环境:

    1. 导入依赖包

    //app build.gradle
    dependencies {
        ...
        implementation deps.lifecycle.viewmodel_ktx
        implementation deps.lifecycle.livedata_ktx
        ...
    }
    

    ## 2. 创建ViewModel类(用于LiveData数据的封装,和UI交互)
    ``` class LiveDataViewModel( private val dataSource: DataSource ) : ViewModel() {...} ```
    ## 3. 布局文件中引用ViewModel对象
     <layout>
         <data>
    		 <variable
    		     name="viewmodel"
    		     type="com.android.example.livedatabuilder.LiveDataViewModel" />
         </data>
         ...
    </layout>
    

    ## 4. Activity绑定ViewModel
    ``` //MainActivity //成员变量 private val viewmodel: LiveDataViewModel by viewModels { LiveDataVMFactory } //onCreate val binding = DataBindingUtil.setContentView( this, R.layout.activity_livedata ) // Set the LifecycleOwner to be able to observe LiveData objects binding.lifecycleOwner = this

    // Bind ViewModel
    binding.viewmodel = viewmodel
    //LifeDataVMFactory
    object LiveDataVMFactory : ViewModelProvider.Factory {
    private val dataSource = DefaultDataSource(Dispatchers.IO)
    override fun <T : ViewModel?> create(modelClass: Class): T {
    @Suppress("UNCHECKED_CAST")
    return LiveDataViewModel(dataSource) as T
    }
    }

    <br/>
    ### 注意:此处构造ViewModel采用的dataSource为DefaultDataSource,后续数据是根据此数据源来进行获取的。
    <br/>
    # 系统时间(Long型)显示
    <br/>
    系统时间的显示,通过在UI上绑定ViewModel,通过getCurrentTime方法后台更新、提交数据,来通知UI进行显示的更新。
    <br/>
    

    //xml
    <TextView
    android:id="@+id/time"
    android:text="@{Long.toString(viewmodel.currentTime)}"
    .../>
    //LiveDataViewModel
    val currentTime = dataSource.getCurrentTime()
    //DefaultDataSource
    override fun getCurrentTime(): LiveData =
    liveData {
    while (true) {
    emit(System.currentTimeMillis())//通知当前系统时间
    delay(1000)//延时1秒
    }
    }

    <br/>
    # 系统时间显示
    <br/>
    系统时间的显示是根据系统获取的Long型变量变化映射得到的,Long值发生变化时,实时更新系统时间显示。
    <br/>
    

    //xml
    <TextView
    android:id="@+id/time_transformed"
    android:text="@{viewmodel.currentTimeTransformed}"
    .../>
    //LiveDataViewModel 此处有两种方式实现
    //1. currentTime变更后实时通知UI更新
    val currentTimeTransformed : LiveData = Transformations.map(currentTime) {
    Date(it).toString()
    }
    //2. 延时500ms后通知
    val currentTimeTransformed = currentTime.switchMap {
    // timeStampToTime is a suspend function so we need to call it from a coroutine.
    liveData { emit(timeStampToTime(it)) }
    }
    private suspend fun timeStampToTime(timestamp: Long): String {
    delay(500) // Simulate long operation
    val date = Date(timestamp)
    return date.toString()
    }

    <br/>
    # 天气显示
    <br/>
    天气的显示通过动态改变数据源提供的数据,从而通知UI显示(DataSource数据的更新实时通过LiveData传递到UI)。
    <br/>
    

    //xml
    <TextView
    android:id="@+id/current_weather"
    android:text="@{viewmodel.currentWeather}"
    .../>
    //LiveDataViewModel
    val currentWeather: LiveData = liveData {
    emit(LOADING_STRING)
    emitSource(dataSource.fetchWeather())
    }
    //DefaultDataSource
    private val weatherConditions = listOf("Sunny", "Cloudy", "Rainy", "Stormy", "Snowy")
    override fun fetchWeather(): LiveData = liveData {
    var counter = 0
    while (true) {
    counter++
    delay(2000)//延时两秒
    //按顺序循环显示weatherConditions中的天气数据信息
    emit(weatherConditions[counter % weatherConditions.size])
    }
    }

    <br/>
    # 远端数据显示
    <br/>
    远端数据的请求通过Button的点击事件触发,数据获取成功后,通知TextView进行数据显示。
    <br/>
    

    //xml
    <TextView
    android:id="@+id/cached_value"
    android:text="@{viewmodel.cachedValue}"
    .../>
    <Button
    android:id="@+id/refresh_button"
    android:onClick="@{() -> viewmodel.onRefresh()}"
    .../>
    //LiveDataViewModel
    val cachedValue = dataSource.cachedData
    fun onRefresh() {
    // Launch a coroutine that reads from a remote data source and updates cache
    viewModelScope.launch {
    dataSource.fetchNewData()
    }
    }
    //DefaultDataSource
    private val _cachedData = MutableLiveData("This is old data")
    override val cachedData: LiveData = _cachedData
    override suspend fun fetchNewData() {
    // Force Main thread
    withContext(Dispatchers.Main) {
    _cachedData.value = "Fetching new data..."
    _cachedData.value = simulateNetworkDataFetch()
    }
    }
    private var counter = 0
    // Using ioDispatcher because the function simulates a long and expensive operation.
    private suspend fun simulateNetworkDataFetch(): String = withContext(ioDispatcher) {
    delay(3000)//延时3秒
    counter++
    "New data from request #$counter"//返回此字符串
    }

    <br/>
    ##### 小提示:本例中的viewModelScope使用的是Kotlin Coroutines(协程)功能,更多协程使用方法,请查看Coroutines在架构组件中的应用:[官方文档链接](https://developer.android.google.cn/topic/libraries/architecture/coroutines)[]()
    <br/>
    远端数据的更新流程为:<br/><br/>
    <center>
    ![file](https://img2018.cnblogs.com/blog/1820853/201909/1820853-20190930133422779-1614304702.jpg)
    </center>
    <br/>
    将上述四个控件分别绑定对应的LiveData对象,增加其数据变化,就能够实现前文描述的APP动态变化效果了。
    
    <br/>
    [帮助文档](https://developer.android.google.cn/topic/libraries/architecture/livedata) 
    &ensp;
    [源码路径](https://github.com/android/architecture-components-samples)<br/><br/>
    小技巧: github 代码下载速度慢,可以克隆到码云上(gitee.com)再下载。
    <br/><br/>
    通过这四个控件的LiveData与UI的交互使用,你学会如何使用LiveData了吗?
    
    
    <br/><br/>
    <center><font color='green'>欢迎关注公众号,留言讨论更多技术问题。</center>
    <center>
    ![file](https://img2018.cnblogs.com/blog/1820853/201909/1820853-20190930133422967-2082437845.jpg)
    </center>
  • 相关阅读:
    并查集-B
    ->的用法
    PTA-1042 字符统计
    PAT 1040有几个PAT
    assembly x86(nasm)修改后的日常
    python接口自动化之操作常用数据库mysql、oracle
    os模块常用方法
    python 多线程编程并不能真正利用多核的CPU
    连接mysql数据库
    python之用yagmail模块发送邮件
  • 原文地址:https://www.cnblogs.com/danvie/p/11612370.html
Copyright © 2011-2022 走看看