我正在使用Retrofit 2,我在这一行得到一个空指针异常:
RetrofitClient.APIError error = RetrofitClient.ErrorUtils.parseError(response, retrofit);
错误为空.更多细节:
这是API返回错误的格式:
{ "error": { "message": "Incorrect credentials", "statusCode": 401 } }
这是我的登录回调代码:
new Callback() { @Override public void onResponse(Response response, Retrofit retrofit) { if (listener != null) { if (response.isSuccess() && response.body() != null) { User user = RetrofitUserToUserMapper.fromRetrofitUser(response.body().getLoginUser()); } else { RetrofitClient.APIError error = RetrofitClient.ErrorUtils.parseError(response, retrofit); listener.onUserLoginFailure(error.getErrorMessage()); // NPE - error is null } } } @Override public void onFailure(Throwable t) { if (listener != null) { listener.onUserLoginFailure(""); } } }
这是我的Retrofit 2课程:
public class RetrofitClient { public static final String API_ROOT = "http://example.com/api/v1/"; private static final String HEADER_OS_VERSION = "X-OS-Type"; private static final String HEADER_APP_VERSION = "X-App-Version"; private static final String HEADER_OS_VERSION_VALUE_ANDROID = "android"; private RetrofitClient() { } private static Retrofit INSTANCE; public static Retrofit getInstance() { if (INSTANCE == null) { setupRestClient(); } return INSTANCE; } public static void setupRestClient() { OkHttpClient httpClient = new OkHttpClient(); addHeadersRequiredForAllRequests(httpClient, BuildConfig.VERSION_NAME); INSTANCE = new Retrofit.Builder() .baseUrl(API_ROOT) .addConverterFactory(GsonConverterFactory.create()) .client(httpClient) .build(); } private static void addHeadersRequiredForAllRequests(OkHttpClient httpClient, final String appVersion) { class RequestInterceptor implements Interceptor { @Override public com.squareup.okhttp.Response intercept(Chain chain) throws IOException { Request request = chain.request().newBuilder() .addHeader(HEADER_OS_VERSION, HEADER_OS_VERSION_VALUE_ANDROID) .addHeader(HEADER_APP_VERSION, appVersion) .build(); return chain.proceed(request); } } httpClient.networkInterceptors().add(new RequestInterceptor()); } public static class ErrorUtils { public static APIError parseError(Response> response, Retrofit retrofit) { Converterconverter = retrofit.responseConverter(APIError.class, new Annotation[0]); APIError error; try { error = converter.convert(response.errorBody()); } catch (IOException e) { e.printStackTrace(); return new APIError(); } catch (Exception e) { e.printStackTrace(); return new APIError(); } return error; } } public static class APIError { @SerializedName("error") public ErrorResponse loginError; public ErrorResponse getLoginError() { return loginError; } public String getErrorMessage() { return loginError.message; } private class ErrorResponse { @SerializedName("message") private String message; @SerializedName("statusCode") public int statusCode; public String getMessage() { return message; } public int getStatusCode() { return statusCode; } @Override public String toString() { return "LoginErrorResponseBody{" + "message='" + getMessage() + '\'' + ", statusCode=" + statusCode + '}'; } public void setMessage(String message) { this.message = message; } } } }
我从本教程获得了错误utils类,但稍微改了一下因为它们的示例中的错误格式不同:
编辑:这是Converter
班级:
/** * Convert objects to and from their representation as HTTP bodies. Register a converter with * Retrofit using {@link Retrofit.Builder#addConverterFactory(Factory)}. */ public interface Converter{ T convert(F value) throws IOException; abstract class Factory { /** * Create a {@link Converter} for converting an HTTP response body to {@code type} or null if it * cannot be handled by this factory. */ public Converter fromResponseBody(Type type, Annotation[] annotations) { return null; } /** * Create a {@link Converter} for converting {@code type} to an HTTP request body or null if it * cannot be handled by this factory. */ public Converter, RequestBody> toRequestBody(Type type, Annotation[] annotations) { return null; } } }
BNK.. 6
更新:
如果要使用自定义类而不是JSONObject
下面的类,可以参考以下内容:
自定义类:
public class ResponseError { Error error; class Error { int statusCode; String message; } }
将以下内容添加到WebAPIService
界面:
@GET("/api/geterror") CallgetError2();
然后,里面MainActivity.java
:
CallresponseErrorCall = service.getError2(); responseErrorCall.enqueue(new Callback () { @Override public void onResponse(Response response, Retrofit retrofit) { if (response.isSuccess() && response.body() != null){ Log.i(LOG_TAG, response.body().toString()); } else { if (response.errorBody() != null){ RetrofitClient.APIError error = RetrofitClient.ErrorUtils.parseError(response, retrofit); Log.e(LOG_TAG, error.getErrorMessage()); } } } @Override public void onFailure(Throwable t) { Log.e(LOG_TAG, t.toString()); } });
我刚RetrofitClient
用我的网络服务测试了你的课程.我对你的APIError
类做了一个小的更新,如下所示(添加2个构造函数,实际上它们没有被调用):
public APIError(){ this.loginError = new ErrorResponse(); } public APIError(int statusCode, String message) { this.loginError = new ErrorResponse(); this.loginError.statusCode = statusCode; this.loginError.message = message; }
接口:
public interface WebAPIService { @GET("/api/geterror") CallgetError(); }
主要活动:
// Retrofit 2.0-beta2 Retrofit retrofit = new Retrofit.Builder() .baseUrl(API_URL_BASE) .addConverterFactory(GsonConverterFactory.create()) .build(); WebAPIService service = retrofit.create(WebAPIService.class); CalljsonObjectCall = service.getError(); jsonObjectCall.enqueue(new Callback () { @Override public void onResponse(Response response, Retrofit retrofit) { if (response.isSuccess() && response.body() != null){ Log.i(LOG_TAG, response.body().toString()); } else { if (response.errorBody() != null){ RetrofitClient.APIError error = RetrofitClient.ErrorUtils.parseError(response, retrofit); Log.e(LOG_TAG, error.getErrorMessage()); } } } @Override public void onFailure(Throwable t) { Log.e(LOG_TAG, t.toString()); } });
我的Web服务(Asp.Net Web API):
根据您的JSON响应数据,我使用了以下代码:
[Route("api/geterror")] public HttpResponseMessage GetError() { var detailError = new { message = "Incorrect credentials", statusCode = 401 }; var myError = new { error = detailError }; return Request.CreateResponse(HttpStatusCode.Unauthorized, myError); }
它的工作原理!希望能帮助到你!
更新:
如果要使用自定义类而不是JSONObject
下面的类,可以参考以下内容:
自定义类:
public class ResponseError { Error error; class Error { int statusCode; String message; } }
将以下内容添加到WebAPIService
界面:
@GET("/api/geterror") CallgetError2();
然后,里面MainActivity.java
:
CallresponseErrorCall = service.getError2(); responseErrorCall.enqueue(new Callback () { @Override public void onResponse(Response response, Retrofit retrofit) { if (response.isSuccess() && response.body() != null){ Log.i(LOG_TAG, response.body().toString()); } else { if (response.errorBody() != null){ RetrofitClient.APIError error = RetrofitClient.ErrorUtils.parseError(response, retrofit); Log.e(LOG_TAG, error.getErrorMessage()); } } } @Override public void onFailure(Throwable t) { Log.e(LOG_TAG, t.toString()); } });
我刚RetrofitClient
用我的网络服务测试了你的课程.我对你的APIError
类做了一个小的更新,如下所示(添加2个构造函数,实际上它们没有被调用):
public APIError(){ this.loginError = new ErrorResponse(); } public APIError(int statusCode, String message) { this.loginError = new ErrorResponse(); this.loginError.statusCode = statusCode; this.loginError.message = message; }
接口:
public interface WebAPIService { @GET("/api/geterror") CallgetError(); }
主要活动:
// Retrofit 2.0-beta2 Retrofit retrofit = new Retrofit.Builder() .baseUrl(API_URL_BASE) .addConverterFactory(GsonConverterFactory.create()) .build(); WebAPIService service = retrofit.create(WebAPIService.class); CalljsonObjectCall = service.getError(); jsonObjectCall.enqueue(new Callback () { @Override public void onResponse(Response response, Retrofit retrofit) { if (response.isSuccess() && response.body() != null){ Log.i(LOG_TAG, response.body().toString()); } else { if (response.errorBody() != null){ RetrofitClient.APIError error = RetrofitClient.ErrorUtils.parseError(response, retrofit); Log.e(LOG_TAG, error.getErrorMessage()); } } } @Override public void onFailure(Throwable t) { Log.e(LOG_TAG, t.toString()); } });
我的Web服务(Asp.Net Web API):
根据您的JSON响应数据,我使用了以下代码:
[Route("api/geterror")] public HttpResponseMessage GetError() { var detailError = new { message = "Incorrect credentials", statusCode = 401 }; var myError = new { error = detailError }; return Request.CreateResponse(HttpStatusCode.Unauthorized, myError); }
它的工作原理!希望能帮助到你!