Android APP开发中,开发者们都想有一个公共的组件,能够实现后台数据的监听,同时实时更新到UI进行显示,从而大大简化开发过程。Google针对这一开发需求,提供了Jetpack LiveData组件。下面咱们来一块儿看下LiveData的基本使用方法吧!android
首先,先了解下使用LiveData的优势。git
LiveData遵循观察者模式,实现LifeCycle接口,所以能够监听数据的实时更新,感知应用的生命周期,让开发者可以更多的关注业务具体实现。github
下面咱们来经过一个小Demo来简单介绍下LiveData的基本使用方法。架构
本例中,数据变化通知UI的显示由四个控件体现,分别为:系统时间(Long型)、系统时间、天气、远端数据。针对这四个控件的动态显示,咱们分别来看下其是如何实现的。app
APP首先须要搭建使用LiveData的环境:框架
//app build.gradle dependencies { ... implementation deps.lifecycle.viewmodel_ktx implementation deps.lifecycle.livedata_ktx ... }
class LiveDataViewModel( private val dataSource: DataSource ) : ViewModel() {...}
<layout> <data> <variable name="viewmodel" type="com.android.example.livedatabuilder.LiveDataViewModel" /> </data> ... </layout>
//MainActivity //成员变量 private val viewmodel: LiveDataViewModel by viewModels { LiveDataVMFactory } //onCreate val binding = DataBindingUtil.setContentView<ActivityLivedataBinding>( 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>): T { @Suppress("UNCHECKED_CAST") return LiveDataViewModel(dataSource) as T } }
系统时间的显示,经过在UI上绑定ViewModel,经过getCurrentTime方法后台更新、提交数据,来通知UI进行显示的更新。
ide
//xml <TextView android:id="@+id/time" android:text="@{Long.toString(viewmodel.currentTime)}" .../> //LiveDataViewModel val currentTime = dataSource.getCurrentTime() //DefaultDataSource override fun getCurrentTime(): LiveData<Long> = liveData { while (true) { emit(System.currentTimeMillis())//通知当前系统时间 delay(1000)//延时1秒 } }
系统时间的显示是根据系统获取的Long型变量变化映射获得的,Long值发生变化时,实时更新系统时间显示。
布局
//xml <TextView android:id="@+id/time_transformed" android:text="@{viewmodel.currentTimeTransformed}" .../> //LiveDataViewModel 此处有两种方式实现 //1. currentTime变动后实时通知UI更新 val currentTimeTransformed : LiveData<String> = 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() }
天气的显示经过动态改变数据源提供的数据,从而通知UI显示(DataSource数据的更新实时经过LiveData传递到UI)。
fetch
//xml <TextView android:id="@+id/current_weather" android:text="@{viewmodel.currentWeather}" .../> //LiveDataViewModel val currentWeather: LiveData<String> = liveData { emit(LOADING_STRING) emitSource(dataSource.fetchWeather()) } //DefaultDataSource private val weatherConditions = listOf("Sunny", "Cloudy", "Rainy", "Stormy", "Snowy") override fun fetchWeather(): LiveData<String> = liveData { var counter = 0 while (true) { counter++ delay(2000)//延时两秒 //按顺序循环显示weatherConditions中的天气数据信息 emit(weatherConditions[counter % weatherConditions.size]) } }
远端数据的请求经过Button的点击事件触发,数据获取成功后,通知TextView进行数据显示。
gradle
//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<String> = _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"//返回此字符串 }
远端数据的更新流程为:
将上述四个控件分别绑定对应的LiveData对象,增长其数据变化,就可以实现前文描述的APP动态变化效果了。
帮助文档
源码路径
小技巧: github 代码下载速度慢,能够克隆到码云上(gitee.com)再下载。
经过这四个控件的LiveData与UI的交互使用,你学会如何使用LiveData了吗?
欢迎关注公众号,留言讨论更多技术问题