当前位置: 移动技术网 > IT编程>移动开发>Android > Jetpack系列:LiveData入门级使用方法

Jetpack系列:LiveData入门级使用方法

2019年09月30日  | 移动技术网IT编程  | 我要评论

炸弹台球2,enticeitient blue,estpac

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

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

  • 确保ui与数据状态匹配

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

  • activity停止后数据变化不会导致crash

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

  • 始终使用最新的数据

  • 正确应用配置更改

  • 共享资源

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

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




file



本例中,数据变化通知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<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
    }
}


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


系统时间(long型)显示



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

//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)。

//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进行数据显示。

//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"//返回此字符串
}


小提示:本例中的viewmodelscope使用的是kotlin coroutines(协程)功能,更多协程使用方法,请查看coroutines在架构组件中的应用:



远端数据的更新流程为:



file



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








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



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




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


file

如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复

相关文章:

验证码:
移动技术网