Roh*_*wal 6 android android-livedata android-architecture-lifecycle android-viewmodel android-architecture-components
我的问题与ViewModel有关,第二次返回null,其中observe如果我重复调用服务器,我在函数中没有得到回调.以下是我使用的代码 -
@Singleton
public class NetworkInformationViewModel extends AndroidViewModel {
private LiveData<Resource<NetworkInformation>> networkInfoObservable;
private final APIClient apiClient;
@Inject
NetworkInformationViewModel(@NonNull APIClient apiClient, @NonNull Application application) {
super(application);
this.apiClient = apiClient;
getNetworkInformation();
}
public LiveData<Resource<NetworkInformation>> getNetworkInfoObservable() {
return networkInfoObservable;
}
// making API calls and adding it to Observable
public void getNetworkInformation() {
networkInfoObservable = apiClient.getNetworkInformation();
}
}
Run Code Online (Sandbox Code Playgroud)
在Activity中,ViewModel定义如下 -
final NetworkInformationViewModel networkInformationViewModel =
ViewModelProviders.of(this, viewModelFactory).get(NetworkInformationViewModel.class);
observeViewModel(networkInformationViewModel);
Run Code Online (Sandbox Code Playgroud)
该observeViewModel函数用于添加observable ViewModel.
public void observeViewModel(final NetworkInformationViewModel networkInformationViewModel) {
networkInformationViewModel.getNetworkInfoObservable()
.observe(this, networkInformationResource -> {
if (networkInformationResource != null) {
if (networkInformationResource.status == APIClientStatus.Status.SUCCESS) {
Timber.d("Got network information data");
} else {
final Throwable throwable = networkInformationResource.throwable;
if (throwable instanceof SocketTimeoutException) {
final NetworkInformation networkInformation = networkInformationResource.data;
String error = null;
if (networkInformation != null) {
error = TextUtils.isEmpty(networkInformation.error) ? networkInformation.reply : networkInformation.error;
}
Timber.e("Timeout error occurred %s %s", networkInformationResource.message, error);
} else {
Timber.e("Error occurred %s", networkInformationResource.message);
}
if (count != 4) {
networkInformationViewModel.getNetworkInformation();
count++;
// Uncommenting following line enables callback to be received every time
//observeViewModel(networkInformationViewModel);
}
}
}
});
}
Run Code Online (Sandbox Code Playgroud)
在上面的函数中取消注释以下行允许每次都进行回调,但必须有一个正确的方法来执行此操作.
//observeViewModel(networkInformationViewModel);
Run Code Online (Sandbox Code Playgroud)
请注意: - 我不需要RxJava实现来实现它.
现在的getNetworkInformation()你是:
LiveDataLiveData使用setValue相反,您应该创建一个LiveDataforAPIClient作为成员变量,然后在 getNetworkInformation() 中更新该成员LiveData。
更一般地说,您APIClient是一个数据源。对于数据源,您可以让它们包含在数据更改时更新的成员 LiveData 对象。您可以为这些 LiveData 对象提供 getter,以便在 ViewModel 中访问它们,并最终在您的 Activity/Fragment 中监听它们。这与您获取另一个数据源(例如 Room)并监听 Room 返回的 LiveData 的方式类似。
因此,本例中的代码如下所示:
@Singleton
public class APIClient {
private final MutableLiveData<Resource<NetworkInformation>> mNetworkData = new MutableLiveData<>(); // Note this needs to be MutableLiveData so that you can call setValue
// This is basically the same code as the original getNetworkInformation, instead this returns nothing and just updates the LiveData
public void fetchNetworkInformation() {
apiInterface.getNetworkInformation().enqueue(new Callback<NetworkInformation>() {
@Override
public void onResponse(
@NonNull Call<NetworkInformation> call, @NonNull Response<NetworkInformation> response
) {
if (response.body() != null && response.isSuccessful()) {
mNetworkData.setValue(new Resource<>(APIClientStatus.Status.SUCCESS, response.body(), null));
} else {
mNetworkData.setValue(new Resource<>(APIClientStatus.Status.ERROR, null, response.message()));
}
}
@Override
public void onFailure(@NonNull Call<NetworkInformation> call, @NonNull Throwable throwable) {
mNetworkData.setValue(
new Resource<>(APIClientStatus.Status.ERROR, null, throwable.getMessage(), throwable));
}
});
}
// Use a getter method so that you can return immutable LiveData since nothing outside of this class will change the value in mNetworkData
public LiveData<Resource<NetworkInformation>> getNetworkData(){
return mNetworkData;
}
}
Run Code Online (Sandbox Code Playgroud)
然后在你的 ViewModel 中...
// I don't think this should be a Singleton; ViewModelProviders will keep more than one from being instantiate for the same Activity/Fragment lifecycle
public class SplashScreenViewModel extends AndroidViewModel {
private LiveData<Resource<NetworkInformation>> networkInformationLiveData;
@Inject
SplashScreenViewModel(@NonNull APIClient apiClient, @NonNull Application application) {
super(application);
this.apiClient = apiClient;
// Initializing the observable with empty data
networkInfoObservable = apiClient.getNetworkData()
}
public LiveData<Resource<NetworkInformation>> getNetworkInfoObservable() {
return networkInformationLiveData;
}
}
Run Code Online (Sandbox Code Playgroud)
您的活动可以与您最初编码的活动相同;它只会从 ViewModel 获取并观察 LiveData。
那么 Transformations.switchMap 是做什么用的呢?
switchMap此处没有必要,因为您不需要更改LiveData中的基础实例APIClient。这是因为实际上只有一项正在变化的数据。假设您的 APIClient 由于某种原因需要 4 个不同的 LiveData,并且您想要更改LiveData您观察到的数据:
public class APIClient {
private MutableLiveData<Resource<NetworkInformation>> mNetData1, mNetData2, mNetData3, mNetData4;
...
}
Run Code Online (Sandbox Code Playgroud)
那么假设您的 fetchNetworkInformation 将根据情况引用不同的 LiveData 来观察。它可能看起来像这样:
public LiveData<Resource<NetworkInformation>> getNetworkInformation(int keyRepresentingWhichLiveDataToObserve) {
LiveData<Resource<NetworkInformation>> currentLiveData = null;
switch (keyRepresentingWhichLiveDataToObserve) {
case 1:
currentLiveData = mNetData1;
break;
case 2:
currentLiveData = mNetData2;
break;
//.. so on
}
// Code that actually changes the LiveData value if needed here
return currentLiveData;
}
Run Code Online (Sandbox Code Playgroud)
在这种情况下,实际的LiveData来源getNetworkInformation是变化的,并且您还使用某种参数来确定您想要的 LiveData。在这种情况下,您将使用switchMap,因为您希望确保您在 Activity/Fragment 中调用的观察语句能够观察到从 中返回的 LiveData APIClient,即使您更改了底层 LiveData 实例也是如此。而且你不想再次调用observe。
现在,这是一个有点抽象的示例,但它基本上就是您对Room Dao 的调用所做的事情 - 如果您有一个基于 idDao查询并返回 a 的方法,它将根据 id 返回一个不同的实例。RoomDatabaseLiveDataLiveData
| 归档时间: |
|
| 查看次数: |
3498 次 |
| 最近记录: |