安卓Jetpack进阶——map与switchMap(一)

409 阅读3分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第19天,点击查看活动详情,希望大家多多支持,帮忙点个赞,谢谢!

前言

之前的文章中我们了解了Jetpack组件中ViewModel,LiveData与Lifecycle,在工作中,我已经明明白白的知道了他们的作用,我现在写的每个页面几乎都少不了它们,当然,这也就避免不了我继续深入下去的心,于是我在官网又发现了Jetpack组件LiveData的两个好伙伴-map与switchMap。

image.png image.png

可惜官网不够人性化,这部分的中文资料还是没有完善,不过我已经花费一段时间去阅读,下面就让我们看看它们庐山真面目。

正篇

出现背景与使用场景

在公司开发,大多数时候的项目还是比较复杂的,于是就会出现很多特殊的需求,而且代码也会讲究许多,也就是这个原因,LiveData为了去适应各种不同的需求场景,出现了两种转换方法:map()和switchMap()。 首先,让我们看看map():

map()方法的使用

使用方法的说明,我们就先举一个例子,假设你有了一个用户类Uer类,这个类包含用户姓名与年龄:

data class User(var firstName : String, var lastName : String, var age : Int)

于是我们可以在ViewModel中创建一个相应的LiveData去包含User类型数据:

class MainViewModel(countReserved: Int) : ViewModel() {

    val userLiveData = MutableLiveData<User>()
    ...
}

这时就有问题了,如果在Activity中这就会将整个User类型的LiveData暴露给外部,需求要是说年龄是隐私,不能泄露,我们明确只要用户姓名,这种情形下就是非常糟糕的了,而map()方法就是解决这个问题的:

class MainViewModel(countReserved: Int) : ViewModel() {

    private val userLiveData = MutableLiveData<User>()
    val userName : LiveData<String> = Transformations.map(userLiveData) { user ->
        "${user.firstName} ${user.lastName}"
    }
    ...
 }

这里代码说明了map()方法的作用就是将实际包含数据的LiveData和仅用于观察数据的LiveData进行转换。
上面的代码中需要用户的名称,于是我们调用了Transformations的map()方法去对LiveData数据类型进行转换,这个方法接受了两个参数,第一个是原始LiveData对象,第二个则是转换函数;

image.png 而我们需要在转换函数里编写具体的转换逻辑,而上述代码中转换逻辑也是十分简单的,即将User对象转换称一个只包含用户名称的字符串。

image.png 此外,为了保证数据的封装性,我们将userLiveData声明成private,这样在外部使用只要观察userName这个LiveData即可。

image.png 而当userLiveData数据发生变化时,map()方法会监听到变化而去执行转换函数中的逻辑,接着再将转换之后的数据告知userName观察者。
这样一套下来,我们的map()的工作就完成了,为了防止因为Konltin表达过于简单,导致我们认为转换逻辑方法比较难,我们再看看Java的写法:

image.png 源码也是十分清晰的:

image.png 仅仅就是返回你想要的类型即可。

结语

现在我们对map()方法有了一定的认知了,接下来,我们会去探究switchMap()方法,然后将二者结合使用再应用到我们的实例上演示一番,感谢您的观看!