90

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

switchMap 的官方文档可以在这里找到。

有人可以通过实际示例解释如何以及在何处使用 switchMap 函数吗?

4

6 回答 6

150

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)都会被调用,就像 map 函数一样。但repository.getUserById(id)返回一个LiveData. 所以每次LiveData返回repository.getUserById(id)的值改变时,值userLiveData也会改变。所以 的值userLiveData将取决于 的值的变化userIdLiveData和变化repository.getUserById(id)

实际示例switchMap():假设您有一个用户配置文件,其中包含一个关注按钮和一个设置另一个配置文件信息的下一个配置文件按钮。下一个配置文件按钮将使用另一个 ID 调用 setUserId(),因此userLiveData会发生变化,UI 也会发生变化。关注按钮将调用 DAO 为该用户再添加一个关注者,因此该用户将拥有 301 个关注者而不是 300 个。userLiveData将具有来自 DAO 的存储库的此更新。

于 2017-12-06T14:28:53.740 回答
31

将我的 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 方法

于 2018-05-25T16:05:16.397 回答
26

对于那些想要更多解释下面给出的@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),这将返回一个 LiveData包含值 User(1, "Jane")。所以现在,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 是触发器,repository.getUserById 返回的 LiveData 是“后备”LiveData。

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

于 2018-10-31T04:07:14.483 回答
3

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

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

您可以考虑使用mapifrepository.getUser(it)返回一个简单的User对象,而不是LiveDatauser 的类型变为LiveData<User>.

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

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

user类型是LiveData<User>

于 2021-02-27T12:11:35.650 回答
3

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

于 2020-09-25T13:13:33.827 回答
1

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

于 2021-03-06T07:36:32.597 回答