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
获取success
为false
的情况下返回的数据:
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
的修改就基本完成了,但是我们要使用它的时候还需要在自定义MyGsonConverterFactory
和MyGsonRequestBodyConverter
两个类。
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
方法中,这个时候我们就可以判断是否抛出的是我们自定义的异常,如果是的话,那我们就可以获得当前的msg
和code
值从而去进行一些操作:
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解析接口流程详解的文章就介绍到这了,更多相关Android自定义Converter解析接口内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
相关文章
Android高级组件ImageSwitcher图像切换器使用方法详解
这篇文章主要为大家详细介绍了Android高级组件ImageSwitcher图像切换器的使用方法,具有一定的参考价值,感兴趣的小伙伴们可以参考一下2017-12-12Android 弹出Dialog时隐藏状态栏和底部导航栏的方法
这篇文章主要介绍了Android 弹出Dialog时隐藏状态栏和底部导航栏的实例代码,本文通过实例代码给大家介绍的非常详细,具有一定的参考借鉴价值,需要的朋友可以参考下2019-07-07如何通过Android Logcat插件分析firebase崩溃问题
android crash Crash(应用崩溃)是由于代码异常而导致App非正常退出,导致应用程序无法继续使用,所有工作都停止的现象,本文重点介绍如何通过Android Logcat插件分析firebase崩溃问题,感兴趣的朋友一起看看吧2024-01-01Android消息通知Notification常用方法(发送消息和接收消息)
最近在做消息通知类Notification的相关业务,利用闲暇时间总结一下,主要分为两部分来记录:发送消息和接收消息,对Android消息通知相关知识感兴趣的朋友一起看看吧2024-02-02Android波纹扩散效果之仿支付宝咻一咻功能实现波纹扩散特效
这篇文章主要介绍了Android波纹扩散效果之仿支付宝咻一咻功能实现波纹扩散特效的相关资料,需要的朋友可以参考下2016-02-02Android 6.0上sdcard和U盘路径获取和区分方法
今天小编就为大家分享一篇Android 6.0上sdcard和U盘路径获取和区分方法,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧2018-08-08丢失Android系统库或者Conversion to Dalvik format failed with error
这篇文章主要介绍了丢失Android系统库或者Conversion to Dalvik format failed with error 1错误的解决方法,分析了Android系统库丢失及版本问题的处理技巧,具有一定参考借鉴价值,需要的朋友可以参考下2015-12-12
最新评论