android使用gson和泛型解析服务器回调的封装

android使用gson和泛型解析服务器回调的封装

概述

前面我们介绍了如何使用Gson解析和创建json,这里我们继续介绍如何使用泛型来封装服务器回调。
本文主要的技术点有

  • 使用类的泛型和方法的泛型
  • 结合gson封装服务器json回调

1 建立通用的回调Model

以这个服务器回调为例。

{
  "server_time": 1497611816029,
  "data": {
    "name": "jady",
    "age": 12
  },
  "success": true
}

这个json里面server_timesuccess的类型是固定不变的,但是data的类型却会经常改变,比如这里传回来的是User,另一个接口传回来的可能就是Student了。
首先建立对应的类:

public class ServerCallbackModel<T> {

   private long server_time;
    private T data;
    private boolean success;
    private String err_code;
    private String message;

    public long getServer_time() {
        return server_time;
    }

    public void setServer_time(long server_time) {
        this.server_time = server_time;
    }

    public T getData() {
        return data;
    }

    public void setData(T data) {
        this.data = data;
    }

    public boolean isSuccess() {
        return success;
    }

    public void setSuccess(boolean success) {
        this.success = success;
    }

    public String getErr_code() {
        return err_code;
    }

    public void setErr_code(String err_code) {
        this.err_code = err_code;
    }

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }

}

2 封装服务器回调

这里我们写的服务器回调是基于已经拿到服务器回调的json字符串。

2.1 回调的抽象基类:

public abstract class HttpCallback<T> {

    public static final String TAG = "HttpCallback";

    protected Type genericityType;

    public HttpCallback() {
        Type genericSuperclass = getClass().getGenericSuperclass();
        if (genericSuperclass instanceof ParameterizedType) {
            this.genericityType = ((ParameterizedType) genericSuperclass).getActualTypeArguments()[0];
        } else {
            this.genericityType = Object.class;
        }
    }

    public abstract void onResolve(T t);

    public abstract void onFailed(String err_code, String message);

    public Type getGenericityType() {
        return genericityType;
    }
}

这里定义了一个构造方法,两个抽象方法,我们先看构造方法,

Type genericSuperclass = getClass().getGenericSuperclass();
if (genericSuperclass instanceof ParameterizedType) {
     this.genericityType = ((ParameterizedType) genericSuperclass).getActualTypeArguments()[0];
} else {
     this.genericityType = Object.class;
}

Type: Java中所有类型的公共高级接口。它们包括原始类型、参数化类型、数组类型、类型变量和基本类型。
getGenericSuperclass()获得带有泛型的父类: 获得带有泛型的父类。
ParameterizedType: 参数化类型,即泛型。
getActualTypeArguments:获取参数化类型的数组,泛型参数可能有多个

getActualTypeArguments()[0]得到了泛型的第一个参数T的类型,赋值给代表当前类泛型类型的成员变量genericityType。如果不是参数化类型,比如在接收服务器回调的地方没有加泛型类型,那么我们就给genericityType赋值Object的class对象。

genericityType是用来在后面作为Gson解析的类型参数的。

再来看看抽象方法:

public abstract void onResolve(String json);
public abstract void onFailed(String err_code, String message);

聪明的你一定发现了没有onSuccess(),别急,看到后面你就明白了。
onResolve()就是用来解析json的了,子类需要重写它来具体解析。
onFailed是错误回调。

2.2 针对刚才服务器对象封装的抽象子类

public abstract class ServerCallback<T, V> extends HttpCallback<T>{
    @Override
    public void onResolve(String json) {
        boolean returnJson = false;
        if (genericityType instanceof Class) {
            switch (((Class) genericityType).getSimpleName()) {
                case "Object":
                case "String":
                    returnJson = true;
                    break;
                default:
                    break;
            }
        }

        if (returnJson) {
            onSuccess((V) json);
        } else {
            T t = (new Gson()).fromJson(json, genericityType);
            if (t instanceof ServerCallbackModel) {
                ServerCallbackModel<V> callbackData = (ServerCallbackModel) t;
                V result = callbackData.getData();
                if (callbackData.isSuccess()) {
                    this.onSuccess(result);
                } else {
                    onFailed(callbackData.getErr_code(), callbackData.getMessage());
                }
            } else {
                onSuccess((V) t);
            }
        }
    }

    public void onFailed(String error_code, String error_message) {
        if (enableShowToast()) {
            Toast.makeText(HttpManager.mContext, error_message, Toast.LENGTH_SHORT).show();
        }
        onFailure(error_code, error_message);
    }

    public abstract void onSuccess(V data);

    public abstract void onFailure(String error_code, String error_message);

    public boolean enableShowToast() {
        return false;
    }
}

首先,我们定义了一个抽象的带两个类型参数的泛型类,第一个参数是Gson映射的外层对象,比如可以传入我们刚才定义的ServerCallbackModel,第二个参数就是外层对象中的数据了,比如ServerCallbackModel中的data。

然后来分析下类中的方法,先来看看非抽象的方法:

public void onResolve(String json)

这个方法用来解析服务器回调,参数json就是服务器回调的json字符串。
首先判断泛型类型genericityType是不是Class类型的,然后判断genericityType的名字是否为String或者Object,是则直接在成功回调中传入json字符串。
如果不是,则用Gson将json解析出来,实参就是genericityType。此时解析出来的类型如果是我们刚才定义的ServerCallbackModel,如果服务器返回成功,那就将data返回,data的类型就是这个类的第二个类型参数,也是onSuccess的形参类型,我们最终需要的数据。
如果服务器返回失败,会将错误传递给onFailed。

protected void onFailed(String error_code, String error_message)

这个方法主要是拦截错误,用于统一处理所有请求的错误。默认只判断是否需要直接弹toast显示错误信息。

public boolean enableShowToast() 

我们可以考虑是否直接将错误信息弹窗提示出来,只需要重写enableShowToast方法,返回true即可。

再来看看抽象方法,这个就是我们最终在具体的业务层需要重写的方法了。

public abstract void onSuccess(V data);

服务器返回成功的信息后,数据会传递到这里。

public abstract void onFailure(String error_code, String error_message);

错误经过onFailed拦截后,会传递到这里。

3 使用封装的回调

HttpCallback callback = new TmpCallback<ServerCallbackModel<User>,User>() {

   @Override
   public void onSuccess(User data) {

   }

   @Override
   public void onFailure(String error_code, String error_message) {

   }
};
API.testGet(callback);

刚才你看到ServerCallback可能还不理解为什么这个泛型要有两个参数,看到这里你应该就秒懂了,其实服务器传回来的正确错误什么的,我们并不想每个调用的地方都去判断,我们这里想要的只是最终的数据。
本文的Demo地址是我的一个开源库,这个库已经经过了我们公司产品大量用户的考验,欢迎starfork,也欢迎大家提issue

RetrofitClient: https://github.com/Jadyli/RetrofitClient

里面的封装基本都是按照本文的思路写的,当然也可以有所变化,比如有些接口没有success之类的,直接就是上数据,那就可以使用CommonCallback

  • 1
    点赞
  • 2
    收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
©️2022 CSDN 皮肤主题:编程工作室 设计师:CSDN官方博客 返回首页
评论 1

打赏作者

Jadyli1

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值