经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 移动开发 » Android » 查看文章
Jetpack系列:LiveData入门级使用方法
来源:cnblogs  作者:Danvie  时间:2019/10/8 9:05:41  对本文有异议

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

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

  • 确保UI与数据状态匹配

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

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

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

  • 始终使用最新的数据

  • 正确应用配置更改

  • 共享资源

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

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




file



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

框架搭建



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

1. 导入依赖包

  1. //app build.gradle
  2. dependencies {
  3. ...
  4. implementation deps.lifecycle.viewmodel_ktx
  5. implementation deps.lifecycle.livedata_ktx
  6. ...
  7. }


2. 创建ViewModel类(用于LiveData数据的封装,和UI交互)


  1. class LiveDataViewModel(
  2. private val dataSource: DataSource
  3. ) : ViewModel() {...}


3. 布局文件中引用ViewModel对象

  1. <layout>
  2. <data>
  3. <variable
  4. name="viewmodel"
  5. type="com.android.example.livedatabuilder.LiveDataViewModel" />
  6. </data>
  7. ...
  8. </layout>


4. Activity绑定ViewModel


  1. //MainActivity
  2. //成员变量
  3. private val viewmodel: LiveDataViewModel by viewModels { LiveDataVMFactory }
  4. //onCreate
  5. val binding = DataBindingUtil.setContentView<ActivityLivedataBinding>(
  6. this, R.layout.activity_livedata
  7. )
  8. // Set the LifecycleOwner to be able to observe LiveData objects
  9. binding.lifecycleOwner = this
  10. // Bind ViewModel
  11. binding.viewmodel = viewmodel
  12. //LifeDataVMFactory
  13. object LiveDataVMFactory : ViewModelProvider.Factory {
  14. private val dataSource = DefaultDataSource(Dispatchers.IO)
  15. override fun <T : ViewModel?> create(modelClass: Class<T>): T {
  16. @Suppress("UNCHECKED_CAST")
  17. return LiveDataViewModel(dataSource) as T
  18. }
  19. }


注意:此处构造ViewModel采用的dataSource为DefaultDataSource,后续数据是根据此数据源来进行获取的。


系统时间(Long型)显示



系统时间的显示,通过在UI上绑定ViewModel,通过getCurrentTime方法后台更新、提交数据,来通知UI进行显示的更新。

  1. //xml
  2. <TextView
  3. android:id="@+id/time"
  4. android:text="@{Long.toString(viewmodel.currentTime)}"
  5. .../>
  6. //LiveDataViewModel
  7. val currentTime = dataSource.getCurrentTime()
  8. //DefaultDataSource
  9. override fun getCurrentTime(): LiveData<Long> =
  10. liveData {
  11. while (true) {
  12. emit(System.currentTimeMillis())//通知当前系统时间
  13. delay(1000)//延时1秒
  14. }
  15. }


系统时间显示



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

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


天气显示



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

  1. //xml
  2. <TextView
  3. android:id="@+id/current_weather"
  4. android:text="@{viewmodel.currentWeather}"
  5. .../>
  6. //LiveDataViewModel
  7. val currentWeather: LiveData<String> = liveData {
  8. emit(LOADING_STRING)
  9. emitSource(dataSource.fetchWeather())
  10. }
  11. //DefaultDataSource
  12. private val weatherConditions = listOf("Sunny", "Cloudy", "Rainy", "Stormy", "Snowy")
  13. override fun fetchWeather(): LiveData<String> = liveData {
  14. var counter = 0
  15. while (true) {
  16. counter++
  17. delay(2000)//延时两秒
  18. //按顺序循环显示weatherConditions中的天气数据信息
  19. emit(weatherConditions[counter % weatherConditions.size])
  20. }
  21. }


远端数据显示



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

  1. //xml
  2. <TextView
  3. android:id="@+id/cached_value"
  4. android:text="@{viewmodel.cachedValue}"
  5. .../>
  6. <Button
  7. android:id="@+id/refresh_button"
  8. android:onClick="@{() -> viewmodel.onRefresh()}"
  9. .../>
  10. //LiveDataViewModel
  11. val cachedValue = dataSource.cachedData
  12. fun onRefresh() {
  13. // Launch a coroutine that reads from a remote data source and updates cache
  14. viewModelScope.launch {
  15. dataSource.fetchNewData()
  16. }
  17. }
  18. //DefaultDataSource
  19. private val _cachedData = MutableLiveData("This is old data")
  20. override val cachedData: LiveData<String> = _cachedData
  21. override suspend fun fetchNewData() {
  22. // Force Main thread
  23. withContext(Dispatchers.Main) {
  24. _cachedData.value = "Fetching new data..."
  25. _cachedData.value = simulateNetworkDataFetch()
  26. }
  27. }
  28. private var counter = 0
  29. // Using ioDispatcher because the function simulates a long and expensive operation.
  30. private suspend fun simulateNetworkDataFetch(): String = withContext(ioDispatcher) {
  31. delay(3000)//延时3秒
  32. counter++
  33. "New data from request #$counter"//返回此字符串
  34. }


小提示:本例中的viewModelScope使用的是Kotlin Coroutines(协程)功能,更多协程使用方法,请查看Coroutines在架构组件中的应用:官方文档链接



远端数据的更新流程为:



file



将上述四个控件分别绑定对应的LiveData对象,增加其数据变化,就能够实现前文描述的APP动态变化效果了。



帮助文档
?
源码路径


小技巧: github 代码下载速度慢,可以克隆到码云上(gitee.com)再下载。



通过这四个控件的LiveData与UI的交互使用,你学会如何使用LiveData了吗?




欢迎关注公众号,留言讨论更多技术问题。


file

原文链接:http://www.cnblogs.com/danvie/p/11612370.html

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号