gpt4 book ai didi

AndroidViewModel - 进行重复调用不会在观察函数中返回数据

转载 作者:塔克拉玛干 更新时间:2023-11-02 23:10:03 26 4
gpt4 key购买 nike

我的问题与 ViewModel second time returns 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();
}
}

在Activity中,ViewModel定义如下-

final NetworkInformationViewModel networkInformationViewModel =
ViewModelProviders.of(this, viewModelFactory).get(NetworkInformationViewModel.class);
observeViewModel(networkInformationViewModel);

observeViewModel 函数用于在 ViewModel 上添加 observable。

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);
}
}
}
});
}

在上面的函数中取消注释以下行允许回调每次都来,但必须有一个正确的方法来做到这一点。

//observeViewModel(networkInformationViewModel);

请注意:-我不需要 RxJava 实现来实现它。

最佳答案

现在在 getNetworkInformation() 中你是:

  1. 创建一个新的 LiveData
  2. 使用 setValue 更新 LiveData

相反,您应该为 APIClient 创建一个单独的 LiveData 作为成员变量,然后在 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;
}

}

然后在你的 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;
}

}

您的 Activity 可以与您最初编写的代码相同;它只会从 ViewModel 获取并观察 LiveData。

那么 Transformations.switchMap 的用途是什么?

switchMap此处不是必需的,因为您不需要更改 APIClient 中的底层 LiveData 实例。这是因为实际上只有一个变化的数据。假设您的 APIClient 出于某种原因需要 4 个不同的 LiveData,并且您想更改观察到的 LiveData:

public class APIClient {
private MutableLiveData<Resource<NetworkInformation>> mNetData1, mNetData2, mNetData3, mNetData4;

...
}

那么假设你的 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;
}

在这种情况下,来自 getNetworkInformation 的实际 LiveData 是变化的,您还使用某种参数来确定您想要的 LiveData。在这种情况下,您将使用 switchMap,因为您要确保在 Activity/Fragment 中调用的观察语句观察从 APIClient 返回的 LiveData,即使您更改了底层的 LiveData 实例。而且您不想再次调用 observe。

现在这是一个有点抽象的例子,但它基本上就是你对 Room Dao 的调用。做——如果你有一个 Dao 方法根据 id 查询你的 RoomDatabase 并返回一个 LiveData,它会返回一个不同的 LiveData 基于id的实例。

关于AndroidViewModel - 进行重复调用不会在观察函数中返回数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47525827/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com