2015-07-26 5 views
13

Каждый запрос на сервер может возвращать error_code. Я хочу, чтобы обрабатывать эти ошибки в одном месте , когда я использовал AsyncTask у меня был BaseAsyncTask как тотДооснащение и централизованная обработка ошибок

public abstract class BaseAsyncTask<Params, Progress, Result> extends AsyncTask<Params, Progress, Result> { 

    protected Context context; 
    private ProgressDialog progressDialog; 
    private Result result; 

    protected BaseAsyncTask(Context context, ProgressDialog progressDialog) { 
     this.context = context; 
     this.progressDialog = progressDialog; 
    } 

    @Override 
    protected void onPreExecute() { 
     super.onPreExecute(); 
    } 

    @Override 
    protected void onPostExecute(Result result) { 
     super.onPostExecute(result); 
     HttpResponse<ErrorResponse> response = (HttpResponse<ErrorResponse>) result; 
    if(response.getData().getErrorCode() != -1) { 
       handleErrors(response.getData()); 
     }else 
      onResult(result); 

    } 

    private void handleErrors(ErrorResponse errorResponse) { 
    } 
    public abstract void onResult(Result result); 
    } 

Но, используя переоснащения каждый запрос имеет свою обработку ошибок обратного вызова:

    git.getFeed(user,new Callback<gitmodel>() { 
        @Override 
        public void success(gitmodel gitmodel, Response response) { 

        } 

        @Override 
        public void failure(RetrofitError error) { 

        } 
       }); 
      } 
     }); 

Как я могу обрабатывать все ошибки в одном месте?

+0

вы можете создать объект обратного вызова для использования в качестве общего обратного вызова. –

ответ

17

Если вам нужно получить некоторую ошибку «логики», то вам нужна Java логика, так как это не особенность дооснащения так в основном:

  1. Создать обратный вызов вашей реализации, реализующий Дооснащаемый Обратный звонок
  2. Создать базовый объект, который определяет метод «IsError»
  3. Изменить дооснащение RestAdapter для того, чтобы получить обратный вызов вместо Модернизированного Один

MyCallback.java

import android.util.Log; 
import retrofit.Callback; 
import retrofit.client.Response; 

public abstract class MyCallback<T extends MyObject> implements Callback<T> { 

    @Override 
    public final void success(T o, Response response) { 
     if (o.isError()) { 
      // [..do something with error] 
      handleLogicError(o); 
     } 
     else { 
      handleSuccess(o, response); 
     } 
    } 

    abstract void handleSuccess(T o, Response response); 

    void handleLogicError(T o) { 
     Log.v("TAG", "Error because userId is " + o.id); 
    } 
} 

MyObject.java (базовый класс для всех объектов, которые вы получаете от ЗАМЕНЫ)

public class MyObject { 
    public long id; 
    public boolean isError() { 
     return id == 1; 
    } 
} 

MyRealObject.java - это класс, который расширяет базовый объект

public class MyRealObject extends MyObject { 
    public long userId; 
    public String title; 
    public String body; 
} 

RetroInterface.Java - интерфейс, используемый дооснащения вы должны быть знакомы с

import retrofit.http.GET; 
import retrofit.http.Path; 

public interface RetroInterface { 

    @GET("/posts/{id}") 
    void sendGet(@Path("id") int id, MyCallback<MyRealObject> callback); 

} 

И, наконец, кусок кода, где используется вся логика

RestAdapter adapter = new RestAdapter.Builder() 
      .setEndpoint("http://jsonplaceholder.typicode.com") 
      .build(); 

    RetroInterface itf = adapter.create(RetroInterface.class); 
    itf.sendGet(2, new MyCallback<MyRealObject>() { 
     @Override 
     void handleSuccess(MyRealObject o, Response response) { 
      Log.v("TAG", "success"); 
     } 

     @Override 
     public void failure(RetrofitError error) { 
      Log.v("TAG", "failure"); 
     } 
    }); 

Если скопировать и вставить этот код, вы получите ошибка, когда вы выполните itf.sendGet(1, new MyCallback..) и успех для itf.sendGet(2, new MyCallback...)

+0

Да, я должен объедините мой код с предложением @Teo Inke, чтобы получить ваше решение –

7

Не уверен, что я правильно понял, но вы можете создать один Обратный звонок и передать его как параметр ко всем вашим запросам.

Вместо:

  git.getFeed(user,new Callback<gitmodel>() { 
       @Override 
       public void success(gitmodel gitmodel, Response response) { 

       } 

       @Override 
       public void failure(RetrofitError error) { 

       } 
      }); 

Сначала определите свой обратный вызов:

Callback<gitmodel> mCallback = new Callback<gitmodel>() { 
    @Override 
    public void success(gitmodel gitmodel, Response response) { 

    } 

    @Override 
    public void failure(RetrofitError error) { 
     // logic to handle error for all requests 
    } 
}; 

Тогда:

git.getFeed(user, mCallback); 
+1

Я думаю, что Ma7moud спрашивает, предположим, что вызов API был успешным, но он вернул успех: false и error_code: «что-то» вместо успеха: true и successData: «что-то», как мы обрабатываем возврат для error_code - вопрос. В этом случае retrofit рассматривает его как успех, так как API был вызван успешно. –

6

В Модернизированный можно указать ErrorHandler на все запросы.

public class ApiErrorHandler implements ErrorHandler { 

    @Override 
    public Throwable handleError(RetrofitError cause) { 
     //here place your logic for all errors 
     return cause; 
    } 
} 

Применить его RestAdapter

RestAdapter.Builder() 
      .setClient(client) 
      .setEndpoint(endpoint) 
      .setErrorHandler(errorHandler) 
      .build(); 

Я думаю, что это то, что вы просили.

+0

Сервер error_code не похож на «404», это логические ошибки, такие как @Jaseem Abbas, поэтому я не могу поместить для них глобальный обработчик ошибок. –

+0

Итак, вы должны подумать о создании абстрактного calback, сделать свою логику и отправить обратный вызов – jakubbialkowski

0

Довольно просто переделайте пример обработки ошибок. Устанавливается таким образом, что вам не нужно много работать в обработчике «сбоя» вызова для переоснащения, чтобы показать отображаемое пользователем сообщение об ошибке. Работает на всех конечных точках. Есть много обработки исключений, так как наши люди-серверы любят держать нас на ногах, отправляя всевозможные случайные вещи ..!

 retrofit-custom-error-handling.java 
    // on error the server sends JSON 
    /* 
    { "error": { "data": { "message":"A thing went wrong" } } } 
    */ 
    // create model classes.. 
    public class ErrorResponse { 
    Error error; 
    public static class Error { 
    Data data; 
    public static class Data { 
    String message; 
    } 
    } 
    } 
    // 
    /** 
    * Converts the complex error structure into a single string you can get with error.getLocalizedMessage() in Retrofit error handlers. 
    * Also deals with there being no network available 
    * 
    * Uses a few string IDs for user-visible error messages 
    */ 
    private static class CustomErrorHandler implements ErrorHandler { 
    private final Context ctx; 

    public CustomErrorHandler(Context ctx) { 
     this.ctx = ctx; 
    } 

    @Override 
    public Throwable handleError(RetrofitError cause) { 
     String errorDescription; 
     if (cause.isNetworkError()) { 
      errorDescription = ctx.getString(R.string.error_network); 
     } else { 
      if (cause.getResponse() == null) { 
       errorDescription = ctx.getString(R.string.error_no_response); 
      } else { 
// Error message handling - return a simple error to Retrofit handlers.. 
       try { 
        ErrorResponse errorResponse = (ErrorResponse) cause.getBodyAs(ErrorResponse.class); 
        errorDescription = errorResponse.error.data.message; 
       } catch (Exception ex) { 
        try { 
         errorDescription = ctx.getString(R.string.error_network_http_error, cause.getResponse().getStatus()); 
        } catch (Exception ex2) { 
         Log.e(TAG, "handleError: " + ex2.getLocalizedMessage()); 
         errorDescription = ctx.getString(R.string.error_unknown); 
        } 
       } 
      } 
     } 
     return new Exception(errorDescription); 
    } 
} 
// When creating the Server... 
retrofit.RestAdapter restAdapter = new retrofit.RestAdapter.Builder() 
     .setEndpoint(apiUrl) 
     .setLogLevel(retrofit.RestAdapter.LogLevel.FULL) 
     .setErrorHandler(new CustomErrorHandler(ctx)) // use error handler.. 
     .build(); 
server=restAdapter.create(Server.class); 
// Now when calling server methods, get simple error out like this: 
     server.postSignIn(login,new Callback<HomePageResponse>(){ 
@Override 
public void success(HomePageResponse homePageResponse,Response response){ 
// Do success things! 
     } 
@Override 
public void failure(RetrofitError error){ 
     error.getLocalizedMessage(); // <-- this is the message to show to user. 
     } 
     }); 
1

В Retrofit2 вы не можете установить ErrorHandler с методом .setErrorHandler(), но вы можете создать перехватчик раскошелиться все возможные ошибки централизованные в одном месте вашего приложения.

В этом примере у вас есть одно централизованное место для обработки ошибок с помощью Retrofit2 и OkHttpClient. Просто повторно используйте объект «Дооснащение» (retrofit).

Вы можете попробовать этот отдельный пример с помощью специального перехватчика для сетевых и серверных ошибок. Они будут обрабатываться по-разному в Retrofit2, поэтому вам нужно проверить возвращенный код ошибки с сервера по коду ответа (response.code()), и если ответ не был успешным (!response.isSuccessful()).

Для случая, когда пользователь не имеет подключения к сети или серверу, вы должны поймать IOException метода Response response = chain.proceed(chain.request()); и обработать сетевую ошибку в блоке catch.

HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor(); 
    loggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY); 

    OkHttpClient client = new OkHttpClient.Builder() 
      .addInterceptor(loggingInterceptor) 
      .addInterceptor(new Interceptor() { 
       @Override 
       public Response intercept(Chain chain) throws IOException { 
        try { 
         Response response = chain.proceed(chain.request()); 
         if (!response.isSuccessful()) { 
          Log.e("tag", "Failure central - response code: " + response.code()); 
          Log.e("tag", "central server error handling"); 

          // Central error handling for error responses here: 
          // e.g. 4XX and 5XX errors 
          switch (response.code()) { 
           case 401: 
            // do something when 401 Unauthorized happened 
            // e.g. delete credentials and forward to login screen 
            // ... 

            break; 
           case 403: 
            // do something when 403 Forbidden happened 
            // e.g. delete credentials and forward to login screen 
            // ... 

            break; 
           default: 
            Log.e("tag", "Log error or do something else with error code:" + response.code()); 

            break; 
          } 
         } 

         return response; 
        } catch (IOException e) { 
         // Central error handling for network errors here: 
         // e.g. no connection to internet/to server 

         Log.e("tag", e.getMessage(), e); 
         Log.e("tag", "central network error handling"); 

         throw e; 
        } 
       } 
      }) 
      .build(); 

    Retrofit retrofit = new Retrofit.Builder() 
      .baseUrl("http://10.0.2.2:8000/api/v1/") 
      .client(client) 
      .addConverterFactory(GsonConverterFactory.create()) 
      .build(); 

    UserRepository backendRepository = retrofit.create(UserRepository.class); 
    backendRepository.getUser("userId123").enqueue(new Callback<UserModel>() { 
     @Override 
     public void onResponse(Call<UserModel> call, retrofit2.Response<UserModel> response) { 
      Log.d("tag", "onResponse"); 

      if (!response.isSuccessful()) { 
       Log.e("tag", "onFailure local server error handling code:" + response.code()); 
      } else { 
       // its all fine with the request 


      } 
     } 

     @Override 
     public void onFailure(Call<UserModel> call, Throwable t) { 
      Log.e("tag", "onFailure local network error handling"); 
      Log.e("tag", t.getMessage(), t); 

     } 
    }); 

UserRepository пример:

public interface UserRepository { 
    @GET("users/{userId}/") 
    Call<UserModel> getUser(@Path("userId") String userId); 

} 

UserModel пример:

public class UserModel implements Parcelable { 
    @SerializedName("id") 
    @Expose 
    public String id = ""; 

    @SerializedName("email") 
    @Expose 
    public String mail = ""; 

    public UserModel() { 

    } 

    protected UserModel(Parcel in) { 
     id = in.readString(); 
     mail = in.readString(); 
    } 

    public static final Creator<UserModel> CREATOR = new Creator<UserModel>() { 
     @Override 
     public UserModel createFromParcel(Parcel in) { 
      return new UserModel(in); 
     } 

     @Override 
     public UserModel[] newArray(int size) { 
      return new UserModel[size]; 
     } 
    }; 

    @Override 
    public int describeContents() { 
     return 0; 
    } 

    @Override 
    public void writeToParcel(Parcel dest, int flags) { 
     dest.writeString(id); 
     dest.writeString(mail); 
    } 
} 
Смежные вопросы