サーバーへのリクエストごとにerror_code
。 AsyncTaskを使用していたときにこれらのエラーを1か所で処理したい
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) {
}
});
}
});
すべてのエラーを1か所で処理するにはどうすればよいですか?
「ロジック」エラーを取得する必要がある場合は、Javaロジックが必要です。これは、基本的にレトロフィット機能ではないためです。
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(Retrofitから取得するすべてのオブジェクトの基本クラス)
_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-あなたが精通している必要があるretrofitによって使用されるインターフェース
_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...)
が成功します。
正しく理解できていませんが、1つのコールバックを作成して、すべてのリクエストにパラメーターとして渡すことができます。
の代わりに:
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);
Retrofitでは、すべてのリクエストに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();
あなたが求めていたものだと思います。
Retrofit2では、メソッド.setErrorHandler()
を使用してErrorHandlerを設定することはできませんが、アプリケーションの1か所に集中して発生する可能性のあるすべてのエラーをフォークするインターセプターを作成できます。
この例では、Retrofit2とOkHttpClientを使用したエラー処理のための1つの集中管理された場所があります。 Retrofitオブジェクト(retrofit
)を再利用するだけです。
ネットワークおよびサーバーエラーのカスタムインターセプターを使用して、このスタンドアロンの例を試すことができます。これらは両方ともRetrofit2で異なる方法で処理されるため、サーバーから返されたエラーコードを応答コード(response.code()
)で確認し、応答が成功しなかったかどうか(!response.isSuccessful()
)を確認する必要があります。 。
ユーザーがネットワークまたはサーバーに接続していない場合は、メソッドResponse response = chain.proceed(chain.request());
のIOExceptionをキャッチし、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);
}
}
かなり単純に、カスタムエラー処理の例を改造します。ユーザーに表示されるエラーメッセージを表示するために、retrofit呼び出しの「failure」ハンドラーで多くの作業を行う必要がないように設定されています。すべてのエンドポイントで動作します。私たちのサーバーの人々があらゆる種類のランダムなものを送信することによって私たちのつま先を維持したいので、多くの例外処理があります..!
// 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.
}
});