基于Volley框架的返回数据的范型处理

基于Volley框架的返回数据的范型处理

在平时最普通的Volley的网络请求中,我们StringRequest是这样请求网络数据的:

StringRequest stringRequest = new StringRequest("http://www.baidu.com",
        new Response.Listener<String>() {
            @Override
            public void onResponse(String response) {
                Log.d("TAG", response);
            }
        }, new Response.ErrorListener() {
    @Override
    public void onErrorResponse(VolleyError error) {
        Log.e("TAG", error.getMessage(), error);
    }

注意在onResponse的时候是拿到的string类型,拿到string后对其再进行相关的解析,我们是否是可以对其直接封装然后拿到具体想要类型的model数据结构呢?所以对其网络请求架构进行一次封装,到达如下效果:

GetGoodDetailByGidRequest getGoodDetailByGidRequest = new GetGoodDetailByGidRequest(mCouponId,
           new RequestListener<List<CouponModel>>() {
               @Override
               public void onSuccess(List<CouponModel> result) {
               }
               @Override
               public void onError(Exception e) {
                   e.printStackTrace();
                   stopLoadingDialog();
               }
           });

这里我们在构造Request的时候指定了返回数据的类型,这样的话就方便了我们在写业务的时候直接使用解析好的数据结构,具体如何做到的呢?

一、让每个Request基于一个带有范型请求类

public abstract class BaseApiRequest<T>  

这里的T就是目标请求期望的model类
在具体实现的时候继承基类,并指定返回类型,下面是一个例子:

public class GetGoodDetailByGidRequest extends BaseApiRequest<List<CouponModel>> {
    public static final String url = CURL.GoodDetailURL;
    public GetGoodDetailByGidRequest(String goodId, RequestListener<List<CouponModel>> requestListener) {
            super(requestListener);
            this.mUrlParams.put("id", goodId);
    }
    @Override
    public String getBaseUrl() {
            return url;
        }
}

二、在基类中构造网络请求

  protected StringRequest getStringRequest() {
    return new StringRequest(requestMethod, getRequestUrl(),
            response -> parseJson(response),
            error -> requestListener.onError(error)) {
        @Override
        protected Map<String, String> getParams() {
            return mEntityParams;
        }
    };
}

在此处实现可以看到Request在基类中进行,然后分别处理返回结果

三、对返回结果进行解析

    private void parseJson(String response) {
    int responseCode = 0;
    int errorCode = 400;
    try {
        JSONObject jsonObject = new JSONObject(response);

        String resultString = jsonObject.getString("data");

        if (jsonObject.has("code")) {
            responseCode = jsonObject.getInt("code");
        }
        if (jsonObject.has("error")) {
            errorCode = jsonObject.getInt("error");
        }

        if (responseCode == 200 || errorCode == 0) {
            if (!TextUtils.isEmpty(response)) {
                Type type = getTType(requestListener.getClass());
                //泛型是实体或者List等类型
                T t = JsonUtils.fromJson(resultString, type);
                requestListener.onSuccess(t);
                return;
            }
            ToastUtils.showToast("Data is empty!");
        }
        ToastUtils.showToast("Response code is error.");
        requestListener.onError(new ParseError());
    } catch (JSONException e) {
        ToastUtils.showToast(e.toString());
        e.printStackTrace();
    }
}

这里是最关键的一步,由于和后端约定好相关返回字段,那么只需要解析字段中目标model的数据,其中比较重要的是这段代码

Type type = getTType(requestListener.getClass());
//泛型是实体或者List等类型
 T t = JsonUtils.fromJson(resultString, type);
 requestListener.onSuccess(t);

通过封装好的 JsonUtils将String转化为对应的model类型,我们知道json转实体对象的时候,需要指明其类type,那这里的type是如何获取到的呢?

其中getTType ()的具体实现为:

 public static Type getTType(Class<?> clazz) {
    //以Type的形式返回本类直接实现的接口.
    Type[] types = clazz.getGenericInterfaces();
    clazz.getInterfaces();
    if (types.length > 0) {
        //返回表示此类型实际类型参数的 Type 对象的数组
        Type[] interfacesTypes = ((ParameterizedType) types[0]).getActualTypeArguments();
        return interfacesTypes[0];
    }
    return null;
}

通过次方法能够获取到请求实现中所指明的请求类型,其中getGenericInterfaces等相关原理可以阅读:https://my.oschina.net/617669559/blog/3012228

所以对于

public class GetGoodDetailByGidRequest extends BaseApiRequest<List<CouponModel>>

那么获取到的就是List类型

四、通过Listener回调相关解析结果

拿到解析好的result并回调给构造Request方法中的listener使用

T t = JsonUtils.fromJson(resultString, type);
requestListener.onSuccess(t);

这样对整个网络请求后的返回数据直接进行解析方便多了。

总结:

1、本文最主要是对基本Request类进行改造,以达到不需要每次重复写解析返回的String数据

2、在获取目标的类的类型的时候,主要是去获取基类中的“T”类型

3、设计不仅适用用Volley同样适用于其他类似的网络请求框架

小弟不才,如有问题,欢迎指出。

# 安卓

评论

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×