如何以及在何处使用Transformations.switchMap?

时间:2017-12-02 17:42:55

标签: android android-architecture-components android-livedata

在Google最近发布的Android架构组件库中,我们在Transformations类中有两个静态函数。虽然map函数是直截了当且容易理解的,但我发现很难正确理解switchMap函数。

可以找到switchMap的官方文档here

有人可以用实际例子解释如何以及在何处使用switchMap功能?

6 个答案:

答案 0 :(得分:49)

map()函数

LiveData userLiveData = ...;
LiveData userName = Transformations.map(userLiveData, user -> {
     return user.firstName + " " + user.lastName; // Returns String
});

每当userLiveData的值发生变化时,userName也会更新。请注意,我们正在返回String

switchMap()函数中:

MutableLiveData userIdLiveData = ...;
LiveData userLiveData = Transformations.switchMap(userIdLiveData, id ->
    repository.getUserById(id)); // Returns LiveData

void setUserId(String userId) {
     this.userIdLiveData.setValue(userId);
}

每当userIdLiveData的值发生变化时,repository.getUserById(id)都会被调用,就像地图功能一样。但repository.getUserById(id)会返回LiveData。因此,每当LiveData返回的repository.getUserById(id)的值发生变化时,userLiveData的值也会发生变化。因此,userLiveData的值取决于userIdLiveData的更改和repository.getUserById(id)的值的更改。

switchMap()的实际示例:假设您有一个带有关注按钮的用户个人资料和一个设置另一个个人资料信息的下一个个人资料按钮。下一个配置文件按钮将使用另一个ID调用setUserId(),因此userLiveData将更改,UI将更改。按下按钮将调用DAO以向该用户添加一个关注者,因此用户将拥有301个关注者而不是300个。userLiveData将具有来自存储库的此更新,该存储库来自DAO。

答案 1 :(得分:10)

将我的2美分加到@DamiaFuentes答案。

MutableLiveData userIdLiveData = ...;
LiveData userLiveData = Transformations.switchMap(userIdLiveData, id ->
repository.getUserById(id)); // Returns LiveData

void setUserId(String userId) {
     this.userIdLiveData.setValue(userId);
}

仅当至少有一个userLiveData观察者

时,才会调用Transformations.switchMap方法

答案 2 :(得分:4)

对于那些想要对下面给出的@DamiaFuentes switchmap()函数示例进行更多解释的人:

 MutableLiveData userIdLiveData = ...;
 LiveData userLiveData = Transformations.switchMap(userIdLiveData, id ->
     repository.getUserById(id));

 void setUserId(String userId) {
      this.userIdLiveData.setValue(userId);
 }

在存储库包含User(1,“ Jane”)和User(2,“ John”)的情况下,当userIdLiveData值设置为“ 1”时,switchMap将调用getUser(1),它将返回一个包含值User(1,“ Jane”)的LiveData。因此,现在,userLiveData将发出User(1,“ Jane”)。当存储库中的用户更新为User(1,“ Sarah”)时,userLiveData将自动得到通知,并发出User(1,“ Sarah”)。

当使用userId =“ 2”调用setUserId方法时,userIdLiveData的值将更改并自动触发从存储库获取ID为“ 2”的用户的请求。因此,userLiveData发出User(2,“ John”)。由repository.getUserById(1)返回的LiveData作为源被删除。

从此示例中,我们可以了解到userIdLiveData是触发器,存储库返回的LiveData。getUserById是“支持” LiveData。

有关更多参考,请查看:https://developer.android.com/reference/android/arch/lifecycle/Transformations

答案 3 :(得分:1)

传递给switchMap的函数返回LiveData。当您的存储库本身返回LiveData时使用它。

答案 4 :(得分:0)

另一点要考虑是在 switchMap 还是 map 之间进行选择,您必须记住 map 始终将返回值包装在 LiveData 周围,例如

fun getUser(id: Int): User 
...
val userId = MutableLiveData(1)
val user = userId.map { // LiveData<User>
   repository.getUser(it)
}

如果 map 返回一个简单的 repository.getUser(it) 对象而不是 User,因此用户类型变为 LiveData,您可以考虑使用 LiveData<User>

如果 repository.getUser(it) 返回 LiveData<User> 那么最好使用 switchMap

fun getUser(id: Int): LiveData<User>
...
val userId = MutableLiveData(1)
val user = userId.switchMap { // LiveData<User>
   repository.getUser(it)
}

user 类型为 LiveData<User>

答案 5 :(得分:0)

还有一点需要理解。 有人可能会想,因为我们总是在 switchMap() 中返回 LiveData 的新值(新引用),那么我们如何在观察者只设置一次的情况下观察实际值呢? 关键是 Transformations.switchMap 的返回值是 MediatorLiveData,它将新的 LiveData 引用添加为新源(并停用其他源)。