即使没有观察者,如何触发 LiveData SwitchMap
How to trigger LiveData SwitchMap even if there is no observer attached
问题:
switchMap 转换只有在它的结果必须有一个活跃的观察者时才会触发。即使没有观察者,我也试图触发 switchMap 转换。谁能建议我如何实现此功能?下面有一些代码描述了当前的场景。
重现方式:
在ProfileViewModel中,UI可以观察到两个不同的LiveData
- profileLiveData : 观察配置文件数据
- profileApiStateLiveData : 观察从后端获取配置文件数据的 Http Call 的状态
ProfileViewModel.java
public class ProfileViewModel extends AndroidViewModel {
private MutableLiveData<Boolean> getProfileCommand = new MutableLiveData<>();
public ProfileViewModel(@NonNull Application application) {
super(application);
profileLiveData = Transformations.switchMap(getProfileCommand, forceUpdate -> UserRepository.getInstance().getProfile(forceUpdate));
profileApiStateLiveData = UserRepository.getInstance().getProfileApiRequestStatus();
}
public void loadProfile(boolean forceUpdate) {
getProfileCommand.postValue(forceUpdate);
}
// Profile Data : Observable Field
private LiveData<Profile> profileLiveData;
public LiveData<Profile> getProfileLiveData() {
if(profileLiveData == null) profileLiveData = new MutableLiveData<>();
return profileLiveData;
}
// Profile Http Call's State : Observable Field
private LiveData<ApiRequest> profileApiStateLiveData;
public LiveData<ApiRequest> getProfileApiStateLiveData() {
if(profileApiStateLiveData == null) profileApiStateLiveData = new MutableLiveData<>();
return profileApiStateLiveData;
}
}
现在 UI 可以观察配置文件数据和 Http 调用状态的变化。
因此,如果 UI 想要下载并显示 UI 上的配置文件,则 UI 负责观察 profileLiveData 和 profileApiStateLiveData 然后调用ViewModel的方法loadProfile(true);
// Observes Profile Data
mProfileViewModel.getProfileLiveData().observe(this, profileData -> {
// Use profile data here
});
// Observes State of Profile Http Call
mProfileViewModel.getProfileApiStateLiveData().observe(this, profileHttpCallState -> {
// show/hide progress based on http call state
});
// start downloading profile data
mProfileViewModel.loadProfile(true);
我们可以看到这里loadProfile方法会触发switchMap Transformation,会启动Http Call。请注意,switchMap 触发器的发生是因为 UI 正在观察结果 LiveData,即 profileLiveData.
这个场景运行良好。但是如果某个Activity只想发起Http Call,只想观察profileApiStateLiveData而不是profileLiveData,那么switchMap触发永远不会发生,这是因为结果 LiveData profileLiveData.
没有活跃的观察者
/**** Do not observe Profile Data, because here we only need to observe Http Call State ***/
/**** Only Observe State of Profile Http Call ***/
mProfileViewModel.getProfileApiStateLiveData().observe(this, profileHttpCallState -> {
// show/hide progress based on http call state
});
/**** start downloading profile data ***/
mProfileViewModel.loadProfile(true);
/**** The above line does not trigger the switchMap Transformation. ***/
我有一个丑陋的解决方案,我必须在 UI 中为 profileLiveData 添加一个不必要的空白观察者。但这很容易出错,因为其他开发人员可能会忘记为 profileLiveData 添加这个不必要的空白观察者,他们不知道为什么即使在调用时也没有获取配置文件数据方法 loadProfile(true).
The help from Rx experts is much appreciated here :-)
这个问题得到了很好的回答,感谢@arka-prava-basu。 profileLiveData 已从转换中分离出来,现在直接从 Room 数据库中获取。和动作
(UserRepository.getInstance().getProfile(forceUpdate) )
此转换正在执行的操作现已转移到 loadProfile 方法。下面是重构后的代码。
ProfileViewModel.java
public class ProfileViewModel extends AndroidViewModel {
public ProfileViewModel(@NonNull Application application) {
super(application);
profileLiveData = UserRepository.getInstance().getMemberInfo();
profileApiStateLiveData = UserRepository.getInstance().getProfileApiRequestStatus();
}
public void loadProfile(boolean forceDownload) {
if(forceDownload) {
UserRepository.getInstance().initiateProfileDownloading();
}
}
// Profile Data : Observable Field
private LiveData<Profile> profileLiveData;
public LiveData<Profile> getProfileLiveData() {
return profileLiveData;
}
// Profile Http Call's State : Observable Field
private LiveData<ApiRequest> profileApiStateLiveData;
public LiveData<ApiRequest> getProfileApiStateLiveData() {
return profileApiStateLiveData;
}
}
问题:
switchMap 转换只有在它的结果必须有一个活跃的观察者时才会触发。即使没有观察者,我也试图触发 switchMap 转换。谁能建议我如何实现此功能?下面有一些代码描述了当前的场景。
重现方式:
在ProfileViewModel中,UI可以观察到两个不同的LiveData
- profileLiveData : 观察配置文件数据
- profileApiStateLiveData : 观察从后端获取配置文件数据的 Http Call 的状态
ProfileViewModel.java
public class ProfileViewModel extends AndroidViewModel {
private MutableLiveData<Boolean> getProfileCommand = new MutableLiveData<>();
public ProfileViewModel(@NonNull Application application) {
super(application);
profileLiveData = Transformations.switchMap(getProfileCommand, forceUpdate -> UserRepository.getInstance().getProfile(forceUpdate));
profileApiStateLiveData = UserRepository.getInstance().getProfileApiRequestStatus();
}
public void loadProfile(boolean forceUpdate) {
getProfileCommand.postValue(forceUpdate);
}
// Profile Data : Observable Field
private LiveData<Profile> profileLiveData;
public LiveData<Profile> getProfileLiveData() {
if(profileLiveData == null) profileLiveData = new MutableLiveData<>();
return profileLiveData;
}
// Profile Http Call's State : Observable Field
private LiveData<ApiRequest> profileApiStateLiveData;
public LiveData<ApiRequest> getProfileApiStateLiveData() {
if(profileApiStateLiveData == null) profileApiStateLiveData = new MutableLiveData<>();
return profileApiStateLiveData;
}
}
现在 UI 可以观察配置文件数据和 Http 调用状态的变化。 因此,如果 UI 想要下载并显示 UI 上的配置文件,则 UI 负责观察 profileLiveData 和 profileApiStateLiveData 然后调用ViewModel的方法loadProfile(true);
// Observes Profile Data
mProfileViewModel.getProfileLiveData().observe(this, profileData -> {
// Use profile data here
});
// Observes State of Profile Http Call
mProfileViewModel.getProfileApiStateLiveData().observe(this, profileHttpCallState -> {
// show/hide progress based on http call state
});
// start downloading profile data
mProfileViewModel.loadProfile(true);
我们可以看到这里loadProfile方法会触发switchMap Transformation,会启动Http Call。请注意,switchMap 触发器的发生是因为 UI 正在观察结果 LiveData,即 profileLiveData.
这个场景运行良好。但是如果某个Activity只想发起Http Call,只想观察profileApiStateLiveData而不是profileLiveData,那么switchMap触发永远不会发生,这是因为结果 LiveData profileLiveData.
没有活跃的观察者 /**** Do not observe Profile Data, because here we only need to observe Http Call State ***/
/**** Only Observe State of Profile Http Call ***/
mProfileViewModel.getProfileApiStateLiveData().observe(this, profileHttpCallState -> {
// show/hide progress based on http call state
});
/**** start downloading profile data ***/
mProfileViewModel.loadProfile(true);
/**** The above line does not trigger the switchMap Transformation. ***/
我有一个丑陋的解决方案,我必须在 UI 中为 profileLiveData 添加一个不必要的空白观察者。但这很容易出错,因为其他开发人员可能会忘记为 profileLiveData 添加这个不必要的空白观察者,他们不知道为什么即使在调用时也没有获取配置文件数据方法 loadProfile(true).
The help from Rx experts is much appreciated here :-)
这个问题得到了很好的回答,感谢@arka-prava-basu。 profileLiveData 已从转换中分离出来,现在直接从 Room 数据库中获取。和动作
(UserRepository.getInstance().getProfile(forceUpdate) )
此转换正在执行的操作现已转移到 loadProfile 方法。下面是重构后的代码。
ProfileViewModel.java
public class ProfileViewModel extends AndroidViewModel {
public ProfileViewModel(@NonNull Application application) {
super(application);
profileLiveData = UserRepository.getInstance().getMemberInfo();
profileApiStateLiveData = UserRepository.getInstance().getProfileApiRequestStatus();
}
public void loadProfile(boolean forceDownload) {
if(forceDownload) {
UserRepository.getInstance().initiateProfileDownloading();
}
}
// Profile Data : Observable Field
private LiveData<Profile> profileLiveData;
public LiveData<Profile> getProfileLiveData() {
return profileLiveData;
}
// Profile Http Call's State : Observable Field
private LiveData<ApiRequest> profileApiStateLiveData;
public LiveData<ApiRequest> getProfileApiStateLiveData() {
return profileApiStateLiveData;
}
}