Я использую Дооснащение 2, и я получаю исключения нулевого указателя на этой линии:Невозможно разобрать ошибку в Модернизированный 2
RetrofitClient.APIError error = RetrofitClient.ErrorUtils.parseError(response, retrofit);
ошибка равна нулю. Подробнее:
Это формат, что API возвращает ошибку:
{
"error": {
"message": "Incorrect credentials",
"statusCode": 401
}
}
Вот мой Логин код Обратный звонок:
new Callback<LoginResponse>() {
@Override
public void onResponse(Response<LoginResponse> 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("");
}
}
}
Это мой дооснащения 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) {
Converter<ResponseBody, APIError> converter =
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 ошибки из этого учебника, но немного изменил его, поскольку форматирование ошибки в t Пример Наследник отличается:
EDIT: Это 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<F, T> {
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<ResponseBody, ?> 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;
}
}
}
Как его инициализировать? Создайте конструктор для 'APIError', который не принимает никаких аргументов и делает' loginError = new LoginError(); 'внутри конструктора? –
попробовал это, не повезло - 'public APIError() { loginError = new ErrorResponse(); } ' –
Pls см. Мой обновленный ответ – BNK