中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Android怎么使用Retrofit實現自定義Converter解析接口

發布時間:2023-03-13 14:31:37 來源:億速云 閱讀:223 作者:iii 欄目:開發技術

本篇內容介紹了“Android怎么使用Retrofit實現自定義Converter解析接口”的有關知識,在實際案例的操作過程中,不少人都會遇到這樣的困境,接下來就讓小編帶領大家學習一下如何處理這些情況吧!希望大家仔細閱讀,能夠學有所成!

不知道你們在使用Retrofit訪問后臺接口時返回的數據是否是一樣的格式,比如登錄接口,在我們輸入密碼成功或錯誤的時候后臺返回的數據格式是不同的,這樣我們在添加GsonConverterFactory解析后臺數據時由于后臺會返回兩種不同的數據所以會導致Gson解析失敗的錯誤信息。這里以自己項目的登錄接口為例子記錄下自己的解決方案。

登錄成功和失敗的兩種數據格式:

{"success":false,"code":-1,"msg":"密碼錯誤","data":"密碼錯誤"}
{"success":true,"code":1,"msg":"操作成功","data":{"JXHDAPIToken":"1ccf7b01ed544882aacda365c8f620d2"}}

從上面數據中我們可以發現后臺返回的數據只有data中的數據是不一樣,其他幾個字段都是一樣的。這個時候我們可以將幾個相同字段抽取出來,通過修改GsonConverterFactory來實現解析不同數據。

修改GsonConverterFactory:

我們只需要點擊進入GsonConverterFactory的源碼中看看它的代碼,這里面我們只需要修改返回的GsonResponseBodyConverter對象。

@Override
  public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations,
      Retrofit retrofit) {
    TypeAdapter<?> adapter = gson.getAdapter(TypeToken.get(type));
    return new GsonResponseBodyConverter<>(gson, adapter);

所以我們再點擊進入GsonResponseBodyConverter中查看它的代碼結構:

final class GsonResponseBodyConverter<T> implements Converter<ResponseBody, T> {
  private final Gson gson;
  private final TypeAdapter<T> adapter;
  GsonResponseBodyConverter(Gson gson, TypeAdapter<T> adapter) {
    this.gson = gson;
    this.adapter = adapter;
  }
  @Override public T convert(ResponseBody value) throws IOException {
    JsonReader jsonReader = gson.newJsonReader(value.charStream());
    try {
      return adapter.read(jsonReader);
    } finally {
      value.close();
    }
  }
}

我們是無法直接在GsonResponseBodyConverter里面直接進行修改的,所以我們可以自定義一個MyGsonResponseBodyConverter類:

final class MyGsonResponseBodyConverter<T> implements Converter<ResponseBody,T>{
    private Gson gson;
    private Type type;
    public MyGsonResponseBodyConverter(Gson gson, Type type) {
        this.gson = gson;
        this.type = type;
    }
    @Override
    public T convert(ResponseBody value) throws IOException {
        String response = value.string();
        try {
            BaseBean baseBean = gson.fromJson(response,BaseBean.class);
            if (!baseBean.isSuccess()) {
                throw new DataResultException(baseBean.getMsg(),baseBean.getCode());
            }
            return gson.fromJson(JsonUtils.getData(response),type);
        }finally {
            value.close();
        }
    }
}

這里面我們通過自己抽取出來的BaseBean去判斷當前接口返回的字段success,如果為true的情況下我們正常返回數據即可,為false的情況我們通過自定義DataResultException異常類將其拋出。

public class BaseBean {
    private boolean success;
    private int code;
    private String msg;
    public boolean isSuccess() {
        return success;
    }
    public void setSuccess(boolean success) {
        this.success = success;
    }
    public int getCode() {
        return code;
    }
    public void setCode(int code) {
        this.code = code;
    }
    public String getMsg() {
        return msg;
    }
    public void setMsg(String msg) {
        this.msg = msg;
    }
}

通過DataResultException獲取successfalse的情況下返回的數據:

public class DataResultException extends IOException {
    private String msg;
    private int code;
    public DataResultException(String msg, int code) {
        this.msg = msg;
        this.code = code;
    }
    public DataResultException(String message, String msg, int code) {
        super(message);
        this.msg = msg;
        this.code = code;
    }
    public String getMsg() {
        return msg;
    }
    public void setMsg(String msg) {
        this.msg = msg;
    }
    public int getCode() {
        return code;
    }
    public void setCode(int code) {
        this.code = code;
    }
}

這個時候我們對GsonConverterFactory的修改就基本完成了,但是我們要使用它的時候還需要在自定義MyGsonConverterFactoryMyGsonRequestBodyConverter兩個類。

public class MyGsonRequestBodyConverter<T> implements Converter<T, RequestBody> {
    private static final MediaType MEDIA_TYPE = MediaType.parse("application/json; charset=UTF-8");
    private static final Charset UTF_8 = Charset.forName("UTF-8");
    private final Gson gson;
    private final TypeAdapter<T> adapter;
    MyGsonRequestBodyConverter(Gson gson, TypeAdapter<T> adapter) {
        this.gson = gson;
        this.adapter = adapter;
    }
    @Override public RequestBody convert(T value) throws IOException {
        Buffer buffer = new Buffer();
        Writer writer = new OutputStreamWriter(buffer.outputStream(), UTF_8);
        JsonWriter jsonWriter = gson.newJsonWriter(writer);
        adapter.write(jsonWriter, value);
        jsonWriter.close();
        return RequestBody.create(MEDIA_TYPE, buffer.readByteString());
    }

這里主要是為了將之前自定義的MyGsonResponseBodyConverter添加進去,而MyGsonRequestBodyConverter這個類和GsonRequestBodyConverter源碼內容是一樣的,我們直接將內容copy過來即可。

public final class MyGsonConverterFactory extends Converter.Factory {
    public static MyGsonConverterFactory create() {
        return create(new Gson());
    }
    public static MyGsonConverterFactory create(Gson gson) {
        if (gson == null) throw new NullPointerException("gson == null");
        return new MyGsonConverterFactory(gson);
    }
    private final Gson gson;
    private MyGsonConverterFactory(Gson gson) {
        this.gson = gson;
    }
    @Override
    public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations,
                                                            Retrofit retrofit) {
        return new MyGsonResponseBodyConverter<>(gson,type);
    }
    @Override
    public Converter<?, RequestBody> requestBodyConverter(Type type,
                                                          Annotation[] parameterAnnotations, Annotation[] methodAnnotations, Retrofit retrofit) {
        TypeAdapter<?> adapter = gson.getAdapter(TypeToken.get(type));
        return new MyGsonRequestBodyConverter<>(gson, adapter);
    }
}

我們只需要將MyGsonConverterFactory替換之前的GsonConverterFactory即可:addConverterFactory(MyGsonConverterFactory.create())

這個時候我們再去調用之前的登錄接口,當我們登錄失敗的時候會進入onError方法中,這個時候我們就可以判斷是否拋出的是我們自定義的異常,如果是的話,那我們就可以獲得當前的msgcode值從而去進行一些操作:

RetrofitUtils.getInstance().getApi().login()
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Subscriber<LoginResult>() {
                    @Override
                    public void onSubscribe(Subscription s) {
                    }
                    @Override
                    public void onNext(LoginResult loginResult) {
                    }
                    @Override
                    public void onError(Throwable t) {
                     if (t instanceof DataResultException) {
                         DataResultException resultException = (DataResultException) t;
                         Log.d(TAG, "Code: " + resultException.getCode() + "Message:" + resultException.getMessage());
                       }
                    }
                    @Override
                    public void onComplete() {
                    }
                });

這里我們可以對Subscriber進行一下封裝,要不我們每次請求都需要去進行判斷顯得很是繁瑣:

public abstract class MySubscriber<T> implements Subscriber<T> {
    @Override
    public void onSubscribe(Subscription s) {
        s.request(Long.MAX_VALUE);
    }
    @Override
    public void onComplete() {
    }
    @Override
    public void onError(Throwable t) {
        //這里面根據自己項目需求進行操作,比如code判斷。
        if (t instanceof DataResultException) {
            DataResultException resultException = (DataResultException) t;
            Log.d(TAG, "Code: " + resultException.getCode() + "Message:" + resultException.getMessage());
        }
    }

封裝后我們只會調用onNext的方法,當然我們如果需要其他操作的話也可以將其他幾個方法重寫:

RetrofitUtils.getInstance().getApi().login()
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new MySubscriber<LoginResult>() {
                    @Override
                    public void onNext(LoginResult loginResult) {
                       //登錄成功
                    }
                });

“Android怎么使用Retrofit實現自定義Converter解析接口”的內容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業相關的知識可以關注億速云網站,小編將為大家輸出更多高質量的實用文章!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

隆林| 门源| 鱼台县| 崇阳县| 四会市| 宁陵县| 卫辉市| 奉化市| 横山县| 武威市| 伊春市| 天峨县| 勃利县| 策勒县| 香河县| 乐山市| 深水埗区| 集安市| 民权县| 宾阳县| 肥西县| 阳东县| 惠东县| 通山县| 苍南县| 龙南县| 福建省| 双城市| 宝应县| 抚顺市| 怀安县| 大港区| 德钦县| 大冶市| 互助| 梅河口市| 沾益县| 盐山县| 崇明县| 拜城县| 东城区|