Я использую архитектуру MVVM, чтобы поразить веб-службу путем модернизации в студии Android. Я обработал ответ службы в моем классе представления. Но проблема, с которой я столкнулся, заключается в том, как обрабатывать исключения и передавать их моему классу представления. Один из способов - создать конструктор в моем классе Bean и передать ему как ответ, так и ошибку, а также обновить пользовательский интерфейс. Но мне нужен более оптимизированный способ обработки исключений внутри пользовательского интерфейса.
Вот мой код репозитория:
final MutableLiveData<MyBeanClass> myBeanClass = new MutableLiveData<>();
ApiInterface apiInterface = ApiClient.getClientAuthentication().create(ApiInterface.class);
Call<MyBeanClass> call = apiInterface.getData(id);
call.enqueue(new Callback<MyBeanClass>() {
@Override
public void onResponse(Call<MyBeanClass> call, Response<MyBeanClass> response) {
if (response.body()!=null) {
myBeanClass.setValue(response.body());
}
}
@Override
public void onFailure(Call<MyBeanClass> call, Throwable t) {
//How to handle exceptions here and pass the exception to UI without making constructor in bean class
}
});
return myBeanClass;
Вы можете объяснить это с помощью кода?
Привет, Эшмит, как ты справился с этим? Я также сталкиваюсь с той же проблемой и неуверен в процедуре обработки другой ошибки + возникновение исключения.
Посмотрите, как это можно сделать из кода вашего репозитория:
//Take it globally in your repository class, and provide getter for it.
final MutableLiveData<MyBeanClass> myBeanClass = new MutableLiveData<>();
final MutableLiveData<Throwable> error = new MutableLiveData<>();
public void someApiCallMethod() {
// In your method call for API
ApiInterface apiInterface =
ApiClient.getClientAuthentication().create(ApiInterface.class);
Call<MyBeanClass> call = apiInterface.getData(id);
call.enqueue(new Callback<MyBeanClass>() {
@Override
public void onResponse(Call<MyBeanClass> call, Response<MyBeanClass> response) {
if (response.body()!=null) {
myBeanClass.setValue(response.body());
}
// Even you can handle your response error if it's in your response.
}
@Override
public void onFailure(Call<MyBeanClass> call, Throwable t) {
//Set your error live data from here
error.setValue(t);
}
});
}
Из вашего класса ViewModel создайте метод, который вызывает ваш метод API репо, а другой - для предоставления ваших данных в реальном времени, которые будут наблюдаться в вашем пользовательском интерфейсе.
Надеюсь, поможет !.
да, я понял это до репозитория .. но я столкнулся с проблемами в модели просмотра ... не могли бы вы рассказать мне о том, как кодировать модель просмотра, чтобы получить два разных типа данных, то есть ошибку / ответ
На самом деле ответ довольно старый, недавно я узнал, как мы можем обернуть обе вещи отсюда: developer.android.com/jetpack/docs/guide#addendum. Сообщите мне, удовлетворяет ли это ваше дело, и я соответствующим образом отредактирую свой ответ.
Я не могу получить решение по этой ссылке ... я хочу получить имя этого конкретного исключения, которое я получаю в моем классе репозитория, в моем представлении через модель представления ... и я получил ответ от моего класса репо через представление модель на мой взгляд ... но как это можно сделать в случае любого исключения ... как принять это исключение на мой взгляд ........
Вместо создания двух изменяемых классов. Вы можете просто создать объект-оболочку как для состояния ошибки, так и для состояния успеха или даже для состояния загрузки.
data class Resource<out T>(val status: Status, val data: T?, val message: String?) {
companion object {
fun <T> success(data: T?): Resource<T> {
return Resource(SUCCESS, data, null)
}
fun <T> error(msg: String, data: T?): Resource<T> {
return Resource(ERROR, data, msg)
}
fun <T> loading(data: T?): Resource<T> {
return Resource(LOADING, data, null)
}
}
}
А затем используйте данные MutableLive в качестве этого типа
final MutableLiveData<Resource<MyBeanClass>> myBeanClass = new MutableLiveData<>();
ApiInterface apiInterface = ApiClient.getClientAuthentication().create(ApiInterface.class);
Call<MyBeanClass> call = apiInterface.getData(id);
call.enqueue(new Callback<MyBeanClass>() {
@Override
public void onResponse(Call<MyBeanClass> call, Response<MyBeanClass> response) {
if (response.body()!=null) {
myBeanClass.setValue(Resource<MyBeanClass>.success(response.body));
}
}
@Override
public void onFailure(Call<MyBeanClass> call, Throwable t) {
myBeanClass.setValue(Resource<MyBeanClass>.error(t.getLocalizedMessage()));
}
});
return myBeanClass;
Вы можете проверить этот образец Google https://github.com/googlesamples/android-architecture-components/tree/master/GithubBrowserSample
да, я сделал это .. теперь моя проблема в том, как обработать исключение в пользовательском интерфейсе ..?
поместите целое число в качестве свойства в свой объект, чтобы указать статус объекта ресурса (Mybeanclass), например, если ресурс успешен, он будет 1, если ресурс не работает, он будет 0, в этом случае вы можете проверить целочисленное значение объекта и будет ли он 1 или 0 и обработать его
но я хочу сказать, как получить имя конкретного исключения из репозитория в пользовательский интерфейс?
с использованием case класса оболочки невозможно получить данные для модификации, это нарушает структуру ответа данных
Вы можете взаимодействовать здесь. Вызовите метод интерфейса из onFailure и предоставьте реализацию этого интерфейса со стороны пользовательского интерфейса, чтобы при возникновении ошибки yiu находился на стороне вашего пользовательского интерфейса.
Вот полная реализация mvvm с обработкой ошибок. Сначала создайте класс с состоянием пользовательского интерфейса и ресурсом.
public class Resource<T> {
@NonNull public final Status status;
@Nullable public final T data;
@Nullable public final String message;
private Resource(@NonNull Status status, @Nullable T data,
@Nullable String message) {
this.status = status;
this.data = data;
this.message = message;
}
public static <T> Resource<T> success(@NonNull T data) {
return new Resource<>(Status.SUCCESS, data, null);
}
public static <T> Resource<T> error(String msg, @Nullable T data) {
return new Resource<>(Status.ERROR, data, msg);
}
public static <T> Resource<T> loading(@Nullable T data) {
return new Resource<>(Status.LOADING, data, null);
}
public enum Status { SUCCESS, ERROR, LOADING }
}
В вашем классе репозитория сделайте
public LiveData<Resource<MyBeanClass>> getDetail(String movieId) {
final MutableLiveData<Resource<MyBeanClass>> myBeanClass = new MutableLiveData<>();
ApiInterface apiInterface = new ApiClient().getClient().create(ApiInterface.class);
Call<MyBeanClass> call = apiInterface.getData(id);
call.enqueue(new Callback<MyBeanClass>() {
@Override
public void onResponse(Call<MyBeanClass> call, Response<MyBeanClass> response) {
if (response.body() != null) {
MyBeanClass body = response.body();
myBeanClass.setValue(Resource.success(body));
}
}
@Override
public void onFailure(Call<MyBeanClass> call, Throwable t) {
myBeanClass.setValue(Resource.error(t.getMessage(),null));
}
});
return myBeanClass;
}
В вашем классе viewModel
public class MyViewModel extends ViewModel {
private LiveData<Resource<MyBeanClass>> myLiveData;
public void init(String id) {
movieLiveData = new MyRepository().getInstance().getDetail(id);
}
public LiveData<Resource<MyBeanClass>> getMyLiveData() {
return myLiveData;
}
}
И в вашем классе активности
final MyViewModel viewModel =
ViewModelProviders.of(this).get(MyViewModel.class);
viewModel.init(id);
viewModel.getMyLiveData().observe(this, finalData -> {
switch (finalData.status) {
case SUCCESS:
loadDetail(finalData.data);
break;
case LOADING:
break;
case ERROR:
Toast.makeText(this, "no Internet", Toast.LENGTH_SHORT).show();
break;
}
});
Если поможет, не забудьте проголосовать. Удачного кодирования
public MutableLiveData<String> responseMessage = new MutableLiveData<>();
public MutableLiveData<String> errorMessage = new MutableLiveData<>(); ApiInterface apiInterface = ApiClient.getClientAuthentication().create(ApiInterface.class);
Call<MyBeanClass> call = apiInterface.getData(id);
call.enqueue(new Callback<MyBeanClass>() {
@Override
public void onResponse(Call<MyBeanClass> call, Response<MyBeanClass> response) {
if (response.body()==null) {
//pick server error message
JSONObject jObjError = new JSONObject(response.errorBody().string());
Log.d("Error",jObjError.getString("message"))
}else{
myBeanClass.setValue(Resource<MyBeanClass>.success(response.body));
}
}
@Override
public void onFailure(Call<MyBeanClass> call, Throwable t) {
Log.d("Error", t.getMessage());
errorMessage.setValue(t.getMessage());
}
});
просто используйте два MutableLiveData: один для успешного ответа, а другой - для errorResponse, и обновите свой пользовательский интерфейс на основе этих ответов.
Еще один способ - взять другие живые данные на предмет ошибки, установить для них свою ошибку и наблюдать за ней в пользовательском интерфейсе.