Android怎么使用Retrofit实现自定义Converter解析接口

其他教程   发布日期:2023年08月22日   浏览次数:437

本篇内容介绍了“Android怎么使用Retrofit实现自定义Converter解析接口”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!

不知道你们在使用Retrofit访问后台接口时返回的数据是否是一样的格式,比如登录接口,在我们输入密码成功或错误的时候后台返回的数据格式是不同的,这样我们在添加

  1. GsonConverterFactory
解析后台数据时由于后台会返回两种不同的数据所以会导致
  1. Gson
解析失败的错误信息。这里以自己项目的登录接口为例子记录下自己的解决方案。

登录成功和失败的两种数据格式:

  1. {"success":false,"code":-1,"msg":"密码错误","data":"密码错误"}
  1. {"success":true,"code":1,"msg":"操作成功","data":{"JXHDAPIToken":"1ccf7b01ed544882aacda365c8f620d2"}}

从上面数据中我们可以发现后台返回的数据只有data中的数据是不一样,其他几个字段都是一样的。这个时候我们可以将几个相同字段抽取出来,通过修改

  1. GsonConverterFactory
来实现解析不同数据。

修改GsonConverterFactory:

我们只需要点击进入

  1. GsonConverterFactory
的源码中看看它的代码,这里面我们只需要修改返回的
  1. GsonResponseBodyConverter
对象。
  1. @Override
  2. public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations,
  3. Retrofit retrofit) {
  4. TypeAdapter<?> adapter = gson.getAdapter(TypeToken.get(type));
  5. return new GsonResponseBodyConverter<>(gson, adapter);

所以我们再点击进入

  1. GsonResponseBodyConverter
中查看它的代码结构:
  1. final class GsonResponseBodyConverter<T> implements Converter<ResponseBody, T> {
  2. private final Gson gson;
  3. private final TypeAdapter<T> adapter;
  4. GsonResponseBodyConverter(Gson gson, TypeAdapter<T> adapter) {
  5. this.gson = gson;
  6. this.adapter = adapter;
  7. }
  8. @Override public T convert(ResponseBody value) throws IOException {
  9. JsonReader jsonReader = gson.newJsonReader(value.charStream());
  10. try {
  11. return adapter.read(jsonReader);
  12. } finally {
  13. value.close();
  14. }
  15. }
  16. }

我们是无法直接在

  1. GsonResponseBodyConverter
里面直接进行修改的,所以我们可以自定义一个
  1. MyGsonResponseBodyConverter
类:
  1. final class MyGsonResponseBodyConverter<T> implements Converter<ResponseBody,T>{
  2. private Gson gson;
  3. private Type type;
  4. public MyGsonResponseBodyConverter(Gson gson, Type type) {
  5. this.gson = gson;
  6. this.type = type;
  7. }
  8. @Override
  9. public T convert(ResponseBody value) throws IOException {
  10. String response = value.string();
  11. try {
  12. BaseBean baseBean = gson.fromJson(response,BaseBean.class);
  13. if (!baseBean.isSuccess()) {
  14. throw new DataResultException(baseBean.getMsg(),baseBean.getCode());
  15. }
  16. return gson.fromJson(JsonUtils.getData(response),type);
  17. }finally {
  18. value.close();
  19. }
  20. }
  21. }

这里面我们通过自己抽取出来的

  1. BaseBean
去判断当前接口返回的字段
  1. success
,如果为
  1. true
的情况下我们正常返回数据即可,为
  1. false
的情况我们通过自定义
  1. DataResultException
异常类将其抛出。
  1. public class BaseBean {
  2. private boolean success;
  3. private int code;
  4. private String msg;
  5. public boolean isSuccess() {
  6. return success;
  7. }
  8. public void setSuccess(boolean success) {
  9. this.success = success;
  10. }
  11. public int getCode() {
  12. return code;
  13. }
  14. public void setCode(int code) {
  15. this.code = code;
  16. }
  17. public String getMsg() {
  18. return msg;
  19. }
  20. public void setMsg(String msg) {
  21. this.msg = msg;
  22. }
  23. }

通过

  1. DataResultException
获取
  1. success
  1. false
的情况下返回的数据:
  1. public class DataResultException extends IOException {
  2. private String msg;
  3. private int code;
  4. public DataResultException(String msg, int code) {
  5. this.msg = msg;
  6. this.code = code;
  7. }
  8. public DataResultException(String message, String msg, int code) {
  9. super(message);
  10. this.msg = msg;
  11. this.code = code;
  12. }
  13. public String getMsg() {
  14. return msg;
  15. }
  16. public void setMsg(String msg) {
  17. this.msg = msg;
  18. }
  19. public int getCode() {
  20. return code;
  21. }
  22. public void setCode(int code) {
  23. this.code = code;
  24. }
  25. }

这个时候我们对

  1. GsonConverterFactory
的修改就基本完成了,但是我们要使用它的时候还需要在自定义
  1. MyGsonConverterFactory
  1. MyGsonRequestBodyConverter
两个类。
  1. public class MyGsonRequestBodyConverter<T> implements Converter<T, RequestBody> {
  2. private static final MediaType MEDIA_TYPE = MediaType.parse("application/json; charset=UTF-8");
  3. private static final Charset UTF_8 = Charset.forName("UTF-8");
  4. private final Gson gson;
  5. private final TypeAdapter<T> adapter;
  6. MyGsonRequestBodyConverter(Gson gson, TypeAdapter<T> adapter) {
  7. this.gson = gson;
  8. this.adapter = adapter;
  9. }
  10. @Override public RequestBody convert(T value) throws IOException {
  11. Buffer buffer = new Buffer();
  12. Writer writer = new OutputStreamWriter(buffer.outputStream(), UTF_8);
  13. JsonWriter jsonWriter = gson.newJsonWriter(writer);
  14. adapter.write(jsonWriter, value);
  15. jsonWriter.close();
  16. return RequestBody.create(MEDIA_TYPE, buffer.readByteString());
  17. }

这里主要是为了将之前自定义的

  1. MyGsonResponseBodyConverter
添加进去,而
  1. MyGsonRequestBodyConverter
这个类和
  1. GsonRequestBodyConverter
源码内容是一样的,我们直接将内容copy过来即可。
  1. public final class MyGsonConverterFactory extends Converter.Factory {
  2. public static MyGsonConverterFactory create() {
  3. return create(new Gson());
  4. }
  5. public static MyGsonConverterFactory create(Gson gson) {
  6. if (gson == null) throw new NullPointerException("gson == null");
  7. return new MyGsonConverterFactory(gson);
  8. }
  9. private final Gson gson;
  10. private MyGsonConverterFactory(Gson gson) {
  11. this.gson = gson;
  12. }
  13. @Override
  14. public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations,
  15. Retrofit retrofit) {
  16. return new MyGsonResponseBodyConverter<>(gson,type);
  17. }
  18. @Override
  19. public Converter<?, RequestBody> requestBodyConverter(Type type,
  20. Annotation[] parameterAnnotations, Annotation[] methodAnnotations, Retrofit retrofit) {
  21. TypeAdapter<?> adapter = gson.getAdapter(TypeToken.get(type));
  22. return new MyGsonRequestBodyConverter<>(gson, adapter);
  23. }
  24. }

我们只需要将

  1. MyGsonConverterFactory
替换之前的
  1. GsonConverterFactory
即可:
  1. addConverterFactory(MyGsonConverterFactory.create())

这个时候我们再去调用之前的登录接口,当我们登录失败的时候会进入

  1. onError
方法中,这个时候我们就可以判断是否抛出的是我们自定义的异常,如果是的话,那我们就可以获得当前的
  1. msg
  1. code
值从而去进行一些操作:
  1. RetrofitUtils.getInstance().getApi().login()
  2. .subscribeOn(Schedulers.io())
  3. .observeOn(AndroidSchedulers.mainThread())
  4. .subscribe(new Subscriber<LoginResult>() {
  5. @Override
  6. public void onSubscribe(Subscription s) {
  7. }
  8. @Override
  9. public void onNext(LoginResult loginResult) {
  10. }
  11. @Override
  12. public void onError(Throwable t) {
  13. if (t instanceof DataResultException) {
  14. DataResultException resultException = (DataResultException) t;
  15. Log.d(TAG, "Code: " + resultException.getCode() + "Message:" + resultException.getMessage());
  16. }
  17. }
  18. @Override
  19. public void onComplete() {
  20. }
  21. });

这里我们可以对

  1. Subscriber
进行一下封装,要不我们每次请求都需要去进行判断显得很是繁琐:
  1. public abstract class MySubscriber<T> implements Subscriber<T> {
  2. @Override
  3. public void onSubscribe(Subscription s) {
  4. s.request(Long.MAX_VALUE);
  5. }
  6. @Override
  7. public void onComplete() {
  8. }
  9. @Override
  10. public void onError(Throwable t) {
  11. //这里面根据自己项目需求进行操作,比如code判断。
  12. if (t instanceof DataResultException) {
  13. DataResultException resultException = (DataResultException) t;
  14. Log.d(TAG, "Code: " + resultException.getCode() + "Message:" + resultException.getMessage());
  15. }
  16. }

封装后我们只会调用

  1. onNext
的方法,当然我们如果需要其他操作的话也可以将其他几个方法重写:
  1. RetrofitUtils.getInstance().getApi().login()
  2. .subscribeOn(Schedulers.io())
  3. .observeOn(AndroidSchedulers.mainThread())
  4. .subscribe(new MySubscriber<LoginResult>() {
  5. @Override
  6. public void onNext(LoginResult loginResult) {
  7. //登录成功
  8. }
  9. });

以上就是Android怎么使用Retrofit实现自定义Converter解析接口的详细内容,更多关于Android怎么使用Retrofit实现自定义Converter解析接口的资料请关注九品源码其它相关文章!