您好,登錄后才能下訂單哦!
本篇內(nèi)容介紹了“Android怎么使用Retrofit實(shí)現(xiàn)自定義Converter解析接口”的有關(guān)知識(shí),在實(shí)際案例的操作過(guò)程中,不少人都會(huì)遇到這樣的困境,接下來(lái)就讓小編帶領(lǐng)大家學(xué)習(xí)一下如何處理這些情況吧!希望大家仔細(xì)閱讀,能夠?qū)W有所成!
不知道你們?cè)谑褂肦etrofit訪問(wèn)后臺(tái)接口時(shí)返回的數(shù)據(jù)是否是一樣的格式,比如登錄接口,在我們輸入密碼成功或錯(cuò)誤的時(shí)候后臺(tái)返回的數(shù)據(jù)格式是不同的,這樣我們?cè)谔砑?code>GsonConverterFactory解析后臺(tái)數(shù)據(jù)時(shí)由于后臺(tái)會(huì)返回兩種不同的數(shù)據(jù)所以會(huì)導(dǎo)致Gson
解析失敗的錯(cuò)誤信息。這里以自己項(xiàng)目的登錄接口為例子記錄下自己的解決方案。
登錄成功和失敗的兩種數(shù)據(jù)格式:
{"success":false,"code":-1,"msg":"密碼錯(cuò)誤","data":"密碼錯(cuò)誤"}
{"success":true,"code":1,"msg":"操作成功","data":{"JXHDAPIToken":"1ccf7b01ed544882aacda365c8f620d2"}}
從上面數(shù)據(jù)中我們可以發(fā)現(xiàn)后臺(tái)返回的數(shù)據(jù)只有data中的數(shù)據(jù)是不一樣,其他幾個(gè)字段都是一樣的。這個(gè)時(shí)候我們可以將幾個(gè)相同字段抽取出來(lái),通過(guò)修改GsonConverterFactory
來(lái)實(shí)現(xiàn)解析不同數(shù)據(jù)。
修改GsonConverterFactory:
我們只需要點(diǎn)擊進(jìn)入GsonConverterFactory
的源碼中看看它的代碼,這里面我們只需要修改返回的GsonResponseBodyConverter
對(duì)象。
@Override public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations, Retrofit retrofit) { TypeAdapter<?> adapter = gson.getAdapter(TypeToken.get(type)); return new GsonResponseBodyConverter<>(gson, adapter);
所以我們?cè)冱c(diǎn)擊進(jìn)入GsonResponseBodyConverter
中查看它的代碼結(jié)構(gòu):
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(); } } }
我們是無(wú)法直接在GsonResponseBodyConverter
里面直接進(jìn)行修改的,所以我們可以自定義一個(gè)MyGsonResponseBodyConverter
類(lèi):
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(); } } }
這里面我們通過(guò)自己抽取出來(lái)的BaseBean
去判斷當(dāng)前接口返回的字段success
,如果為true
的情況下我們正常返回?cái)?shù)據(jù)即可,為false
的情況我們通過(guò)自定義DataResultException
異常類(lèi)將其拋出。
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; } }
通過(guò)DataResultException
獲取success
為false
的情況下返回的數(shù)據(jù):
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; } }
這個(gè)時(shí)候我們對(duì)GsonConverterFactory
的修改就基本完成了,但是我們要使用它的時(shí)候還需要在自定義MyGsonConverterFactory
和MyGsonRequestBodyConverter
兩個(gè)類(lèi)。
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
添加進(jìn)去,而MyGsonRequestBodyConverter
這個(gè)類(lèi)和GsonRequestBodyConverter
源碼內(nèi)容是一樣的,我們直接將內(nèi)容copy過(guò)來(lái)即可。
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())
這個(gè)時(shí)候我們?cè)偃フ{(diào)用之前的登錄接口,當(dāng)我們登錄失敗的時(shí)候會(huì)進(jìn)入onError
方法中,這個(gè)時(shí)候我們就可以判斷是否拋出的是我們自定義的異常,如果是的話(huà),那我們就可以獲得當(dāng)前的msg
和code
值從而去進(jìn)行一些操作:
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() { } });
這里我們可以對(duì)Subscriber
進(jìn)行一下封裝,要不我們每次請(qǐng)求都需要去進(jìn)行判斷顯得很是繁瑣:
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) { //這里面根據(jù)自己項(xiàng)目需求進(jìn)行操作,比如code判斷。 if (t instanceof DataResultException) { DataResultException resultException = (DataResultException) t; Log.d(TAG, "Code: " + resultException.getCode() + "Message:" + resultException.getMessage()); } }
封裝后我們只會(huì)調(diào)用onNext
的方法,當(dāng)然我們?nèi)绻枰渌僮鞯脑?huà)也可以將其他幾個(gè)方法重寫(xiě):
RetrofitUtils.getInstance().getApi().login() .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(new MySubscriber<LoginResult>() { @Override public void onNext(LoginResult loginResult) { //登錄成功 } });
“Android怎么使用Retrofit實(shí)現(xiàn)自定義Converter解析接口”的內(nèi)容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業(yè)相關(guān)的知識(shí)可以關(guān)注億速云網(wǎng)站,小編將為大家輸出更多高質(zhì)量的實(shí)用文章!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。