这是在 Android 应用程序上重试 API 调用的按钮的正确方法吗?
Is this the right way to have a button that retries an API call on an Android app?
我正在处理的项目从 API 中获取用户列表,中间没有 Room(仅网络架构)。我实际上让代码按照我希望的方式工作,但我想知道这是否是正确的方法。下面我标记了我有疑问的地方。
我的 UI 是一个由 ListAdapter 支持的 RecyclerView。我有一个 ViewModel (mainViewModel),它正在观察存储库 class 提供的用户列表,还有一个布尔值来显示或不显示 "Try Again" 按钮。
在MainActivity.java我有
// Observing the boolean that represents if the api call failed
mainViewModel.getCallFailure().observe(this, new Observer<Boolean>() {
@Override
public void onChanged(Boolean aBoolean) {
if (aBoolean) {
tryAgainButton.setVisibility(View.VISIBLE);
} else {
tryAgainButton.setVisibility(View.GONE);
}
}
});
// Setting up onClickListener
tryAgainButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mainViewModel.retryCall(); // HERE IS WHERE I'M HAVING DOUBTS
}
});
MainViewModel.java有
public class MainViewModel extends ViewModel {
...
public LiveData<Boolean> getCallFailure(){
return userRepo.getCallFailure();
}
// THIS IS THE METHOD I'M CALLING FROM THE UI
public void retryCall(){
userRepo.getRetryCallback();
}
}
最后,Repository.java 是
public class Repository {
private Call<UsersResponse> retryCall;
private Callback<UsersResponse> callback;
private final MutableLiveData<Boolean> callFailure = new MutableLiveData<>();
public LiveData<List<UserModel>> getListUsers(){
final MutableLiveData<List<UserModel>> users = new MutableLiveData<>();
callFailure.setValue(false);
(Api.getClient().getUsersList()).enqueue(new Callback<UsersResponse>() {
@Override
public void onResponse(Call<UsersResponse> call, Response<UsersResponse> response) {
users.setValue(response.body().getUsersList());
callFailure.setValue(false);
}
@Override
public void onFailure(Call<UsersResponse> call, Throwable t) {
Log.d("Response GET", t.toString());
callFailure.setValue(true);
setCallback(this);
retryCall = call.clone();
}
});
return users;
}
private void setCallback(Callback<UsersResponse> usersResponseCallback) {
callback = usersResponseCallback;
}
public LiveData<Boolean> getCallFailure(){
return callFailure;
}
public void getRetryCallback(){
retryCall.enqueue(callback);
}
}
我试图仅提及我认为相关的代码,我管理 ProgressDialog 的方式与我在存储库中处理布尔值 callFailure
的方式相同,它正在创造奇迹。但老实说,在 MainActivity.java 文件中调用 mainViewModel.retryCall();
感觉有些不对劲,我非常感谢任何建议!
在我使用 MVVM 制作的项目中,我的活动和片段会像您公开的那样通知我的 ViewModel(通过调用一个类似于触发器的方法)并通过 LiveData 观察结果。
对我来说很奇怪的一件事是您的存储库存储了状态的一部分(重试和失败)。在我的项目中,我将此逻辑放在 ViewModel 中,我的存储库在这里执行简单的操作(如网络调用)。但这更多是个人选择。
EDIT:这是我根据您的代码完成此操作的方法(也许存在更好的方法)。
基本上,我更喜欢在 ViewModel 中管理 LiveData 对象而不是在存储库中,因为在我看来,存储库层只是应用程序和数据(在网络或数据库中)之间的桥梁,并且UI 的状态(如重试按钮可见性)必须由 ViewModel 管理。
Repository.java:
public class Repository {
public void getListUsers(Callback<UserResponse> callback) {
(Api.getClient().getUsersList()).enqueue(callback);
}
}
MainViewModel.java:
public class MainViewModel extends ViewModel {
...
private final MutableLiveData<Boolean> callFailure = new MutableLiveData<>();
private final MutableLiveData<List<UserModel>> users = new MutableLiveData<>();
public LiveData<Boolean> getCallFailure() {
return callFailure;
}
public LiveData<Boolean> getUsers() {
return users;
}
// THIS IS THE METHOD I'M CALLING FROM THE UI
public void retryGetUsers() {
callFailure.setValue(false);
getUsers();
}
private void getUsers() {
userRepo.getListUsers(new Callback<UserResponse>(){
@Override
public void onResponse(Call<UsersResponse> call, Response<UsersResponse> response) {
users.setValue(response.body().getUserList());
}
@Override
public void onFailure(Call<UsersResponse> call, Throwable t) {
callFailure.setValue(true);
}
});
}
}
我正在处理的项目从 API 中获取用户列表,中间没有 Room(仅网络架构)。我实际上让代码按照我希望的方式工作,但我想知道这是否是正确的方法。下面我标记了我有疑问的地方。
我的 UI 是一个由 ListAdapter 支持的 RecyclerView。我有一个 ViewModel (mainViewModel),它正在观察存储库 class 提供的用户列表,还有一个布尔值来显示或不显示 "Try Again" 按钮。
在MainActivity.java我有
// Observing the boolean that represents if the api call failed
mainViewModel.getCallFailure().observe(this, new Observer<Boolean>() {
@Override
public void onChanged(Boolean aBoolean) {
if (aBoolean) {
tryAgainButton.setVisibility(View.VISIBLE);
} else {
tryAgainButton.setVisibility(View.GONE);
}
}
});
// Setting up onClickListener
tryAgainButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mainViewModel.retryCall(); // HERE IS WHERE I'M HAVING DOUBTS
}
});
MainViewModel.java有
public class MainViewModel extends ViewModel {
...
public LiveData<Boolean> getCallFailure(){
return userRepo.getCallFailure();
}
// THIS IS THE METHOD I'M CALLING FROM THE UI
public void retryCall(){
userRepo.getRetryCallback();
}
}
最后,Repository.java 是
public class Repository {
private Call<UsersResponse> retryCall;
private Callback<UsersResponse> callback;
private final MutableLiveData<Boolean> callFailure = new MutableLiveData<>();
public LiveData<List<UserModel>> getListUsers(){
final MutableLiveData<List<UserModel>> users = new MutableLiveData<>();
callFailure.setValue(false);
(Api.getClient().getUsersList()).enqueue(new Callback<UsersResponse>() {
@Override
public void onResponse(Call<UsersResponse> call, Response<UsersResponse> response) {
users.setValue(response.body().getUsersList());
callFailure.setValue(false);
}
@Override
public void onFailure(Call<UsersResponse> call, Throwable t) {
Log.d("Response GET", t.toString());
callFailure.setValue(true);
setCallback(this);
retryCall = call.clone();
}
});
return users;
}
private void setCallback(Callback<UsersResponse> usersResponseCallback) {
callback = usersResponseCallback;
}
public LiveData<Boolean> getCallFailure(){
return callFailure;
}
public void getRetryCallback(){
retryCall.enqueue(callback);
}
}
我试图仅提及我认为相关的代码,我管理 ProgressDialog 的方式与我在存储库中处理布尔值 callFailure
的方式相同,它正在创造奇迹。但老实说,在 MainActivity.java 文件中调用 mainViewModel.retryCall();
感觉有些不对劲,我非常感谢任何建议!
在我使用 MVVM 制作的项目中,我的活动和片段会像您公开的那样通知我的 ViewModel(通过调用一个类似于触发器的方法)并通过 LiveData 观察结果。
对我来说很奇怪的一件事是您的存储库存储了状态的一部分(重试和失败)。在我的项目中,我将此逻辑放在 ViewModel 中,我的存储库在这里执行简单的操作(如网络调用)。但这更多是个人选择。
EDIT:这是我根据您的代码完成此操作的方法(也许存在更好的方法)。
基本上,我更喜欢在 ViewModel 中管理 LiveData 对象而不是在存储库中,因为在我看来,存储库层只是应用程序和数据(在网络或数据库中)之间的桥梁,并且UI 的状态(如重试按钮可见性)必须由 ViewModel 管理。
Repository.java:
public class Repository {
public void getListUsers(Callback<UserResponse> callback) {
(Api.getClient().getUsersList()).enqueue(callback);
}
}
MainViewModel.java:
public class MainViewModel extends ViewModel {
...
private final MutableLiveData<Boolean> callFailure = new MutableLiveData<>();
private final MutableLiveData<List<UserModel>> users = new MutableLiveData<>();
public LiveData<Boolean> getCallFailure() {
return callFailure;
}
public LiveData<Boolean> getUsers() {
return users;
}
// THIS IS THE METHOD I'M CALLING FROM THE UI
public void retryGetUsers() {
callFailure.setValue(false);
getUsers();
}
private void getUsers() {
userRepo.getListUsers(new Callback<UserResponse>(){
@Override
public void onResponse(Call<UsersResponse> call, Response<UsersResponse> response) {
users.setValue(response.body().getUserList());
}
@Override
public void onFailure(Call<UsersResponse> call, Throwable t) {
callFailure.setValue(true);
}
});
}
}