在 Google 最近发布的 Android 架构组件库中,我们在Transformations
类中有两个静态函数。虽然该map
功能直截了当且易于理解,但我发现很难正确理解该switchMap
功能。
switchMap 的官方文档可以在这里找到。
有人可以通过实际示例解释如何以及在何处使用 switchMap 函数吗?
在 Google 最近发布的 Android 架构组件库中,我们在Transformations
类中有两个静态函数。虽然该map
功能直截了当且易于理解,但我发现很难正确理解该switchMap
功能。
switchMap 的官方文档可以在这里找到。
有人可以通过实际示例解释如何以及在何处使用 switchMap 函数吗?
在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 的存储库的此更新。
将我的 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 方法
对于那些想要更多解释下面给出的@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
switchMap
要考虑是否在or之间进行选择的另一点map
,您必须记住map
始终将返回值包装在LiveData
例如
fun getUser(id: Int): User
...
val userId = MutableLiveData(1)
val user = userId.map { // LiveData<User>
repository.getUser(it)
}
您可以考虑使用map
ifrepository.getUser(it)
返回一个简单的User
对象,而不是LiveData
user 的类型变为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>
传递给 switchMap 的函数返回 LiveData。当您的存储库本身返回 LiveData 时使用它。
还有一点需要理解。有人可能会认为,由于我们总是在 switchMap() 中返回 LiveData 的新值(新引用),那么我们如何在观察者只设置一次的情况下观察实际值呢?关键是 Transformations.switchMap 的返回值是 MediatorLiveData,它将新的 LiveData 引用添加为新源(并停用其他源)。