超简单的okHttpUtils封装(下)

 

版权声明:转载请注明出处:http://blog.csdn.net/piaomiao8179 https://blog.csdn.net/piaomiao8179/article/details/70888901

前言:

上一篇我们讲到了基本的Okhttp的封装,只需要我们在代码种调用okHttpUtils.getInstance().GET(url, MyCallBack),一句话完事,而且还是链式的,只需要在MyCallBack中处理返回的Response即可,是不是感觉很爽,不要着急,接下来会让你更爽,请自行准备纸巾,条件允许的话也可以为你的宝贝充上气。没有看过上篇文章的,最好看一下,点击即可跳转: 超简单的okhttp封装工具类(上)
好了,废话不多说,进入正题,本篇主要思想是,通过上篇的封装,联网成功后,返回的是Response对象,我们平时联网需要的结果是一个JavaBean或者一个集合,泛型为JavaBean。那么,接下来就是实现直接返回带泛型的集合,而不是还需要我们处理的Response。

MyCallBack接口的改写

首先,在MyCallBack后面加上泛型,到时候需要实例化这个callback时候,自然的把我们需要转换成的JavaBean以泛型的形式传递过去。
本篇采用Gson进行Response的json转换,所以需要根据泛型获取Type对象。获取方法如下:

//根据T获取Type
static Type getSuperclassTypeParameter(Class<?> subclass)
{
    Type superclass = subclass.getGenericSuperclass();
    if (superclass instanceof Class)
    {
        throw new RuntimeException("Missing type parameter.");
    }
    ParameterizedType parameterized = (ParameterizedType) superclass;
    return $Gson$Types.canonicalize(parameterized.getActualTypeArguments()[0]);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

我们原来定义的MyCallBack为接口,此时需要改写成抽象类,因为要用到构造方法进行构造Type对象。具体代码如下:

public abstract class MyCallBack<T> {


public  Type mType;

static Type getSuperclassTypeParameter(Class<?> subclass)
{
    Type superclass = subclass.getGenericSuperclass();
    if (superclass instanceof Class)
    {
        throw new RuntimeException("Missing type parameter.");
    }
    ParameterizedType parameterized = (ParameterizedType) superclass;
    return $Gson$Types.canonicalize(parameterized.getActualTypeArguments()[0]);
}

public MyCallBack() {
    mType = getSuperclassTypeParameter(getClass());
}

public abstract void onLoadingBefore(Request request);
//第二个参数为传入的泛型,也就是说返回的结果直接就是我们需要的类型
public abstract void onSuccess(Response response, T result);

public abstract void onFailure(Request request, Exception e);

public abstract void onError(Response response);

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29

OkHttpUtils工具类的改写

我们主要是改写Response返回的地方,也就是联网逻辑这一块,即requestNetWork()方法。具体请看代码实现,注释很清晰。

private void requestNetWork(Request request, MyCallBack<Object> callBack) {

    /**
     * 处理连网逻辑,此处只处理异步操作enqueue
     */
    callBack.onLoadingBefore(request);

    mOkHttpClient.newCall(request).enqueue(new Callback() {
        @Override
        public void onFailure(Call call, IOException e) {
            mHandler.post(() -> callBack.onFailure(request, e));

        }

        @Override
        public void onResponse(Call call, Response response) throws IOException {
            if (response.isSuccessful()) {

                String resultStr = response.body().string();
                if (callBack.mType == String.class) {
                    // 如果想要返回字符串 直接返回就行
                    mHandler.post(() -> callBack.onSuccess(response, resultStr));
                } else {
                    // 需要返回解析好的javaBean集合
                    try {
                        // 此处暂时写成object,使用时返回具体的带泛型的集合
                        Object obj = mGson.fromJson(resultStr, callBack.mType);
                        mHandler.post(() -> callBack.onSuccess(response, obj));
                    } catch (Exception e) {
                        // 解析错误时
                        mHandler.post(() -> callBack.onError(response));
                    }

                }

            } else {
                mHandler.post(() -> callBack.onError(response));
            }
        }
    });


}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43

界面联网具体操作

具体使用方法如下:在Fragment的OnCreatView方法中写的逻辑,根据需求自己选择在哪里联网,此处只是测试,不建议在这个方法中处理。会阻塞界面显示。

private String url = "http://222.133.11.150:8402/EnvService/Version/CheckVersion?imei=860806029044186&version=111";

@Nullable
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {

    OkHttpUtils.getInstance().Get(url, new MyCallBack<ceshiBean>() {

        @Override
        public void onLoadingBefore(Request request) {

        }

        @Override
        public void onSuccess(Response response, ceshiBean result) {
            System.out.println("-----" + result.getStrApkUrl());
        }

        @Override
        public void onFailure(Request request, Exception e) {

        }

        @Override
        public void onError(Response response) {

        }
    });

    return  inflater.inflate(R.layout.fragment_home,container,false);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31

ceshiBean的代码

这是我们根据接口写的javaBean对象
public class ceshiBean {

/**
 * StrApkUrl : http://222.133.11.150:8402/EnvService/versioninfo/EnvDS_DZ.apk
 * StrUpdateDate : 2017.4.18
 * StrUpdateFlag : 0
 * StrUpdateLog :
 1.城市空气模块,新增加乡镇站、边界站、农村站交通站。

 * StrVersionCode : 110
 * StrVersionName : 1.1.0
 */

private String StrApkUrl;
private String StrUpdateDate;
private String StrUpdateFlag;
private String StrUpdateLog;
private String StrVersionCode;
private String StrVersionName;

public String getStrApkUrl() {
    return StrApkUrl;
}

public void setStrApkUrl(String StrApkUrl) {
    this.StrApkUrl = StrApkUrl;
}

public String getStrUpdateDate() {
    return StrUpdateDate;
}

public void setStrUpdateDate(String StrUpdateDate) {
    this.StrUpdateDate = StrUpdateDate;
}

public String getStrUpdateFlag() {
    return StrUpdateFlag;
}

public void setStrUpdateFlag(String StrUpdateFlag) {
    this.StrUpdateFlag = StrUpdateFlag;
}

public String getStrUpdateLog() {
    return StrUpdateLog;
}

public void setStrUpdateLog(String StrUpdateLog) {
    this.StrUpdateLog = StrUpdateLog;
}

public String getStrVersionCode() {
    return StrVersionCode;
}

public void setStrVersionCode(String StrVersionCode) {
    this.StrVersionCode = StrVersionCode;
}

public String getStrVersionName() {
    return StrVersionName;
}

public void setStrVersionName(String StrVersionName) {
    this.StrVersionName = StrVersionName;
}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66

总结

到此为止,已经实现了简化逻辑,只需要调用方法时候传入泛型javaBean即可,就能直接获取数据了。

可能有的小伙伴会说,这只是单个javaBean对象的解析,如果我们接口返回的是好对个javaBean的集合,怎么办,so easy,只需要把泛型写成List的形式就好了,直接给你返回一个集合数据集,太爽了。

当然,还有更方便的写法,你可以再次自定义一个具体的CallBack继承MyCallBack,实现里面的方法,在联网开始前显示加载对话框,解析结束隐藏对话框,处理相应的逻辑。那么在前台界面只需要处理你自己的数据就可以了。

声明:本文实现思路是参考IVan的封装思路,只做学习用途。

OkHttpUtils改进后的源码


public class OkHttpUtils {

    /**
     * 网络访问要求singleton
     */
    private static OkHttpUtils instance;

    // 必须要用的okhttpclient实例,在构造器中实例化保证单一实例
    private OkHttpClient mOkHttpClient;

    public static final MediaType JSON = MediaType.
            parse("application/json; charset=utf-8");

    private Handler mHandler;

    private Gson mGson;

    private OkHttpUtils() {
        /**
         * okHttp3中超时方法移植到Builder中
         */
        mOkHttpClient = (new OkHttpClient()).newBuilder()
                    .connectTimeout(10, TimeUnit.SECONDS)
                    .readTimeout(10, TimeUnit.SECONDS)
                    .writeTimeout(30, TimeUnit.SECONDS)
                    .build();

        mHandler = new Handler(Looper.getMainLooper());

        mGson = new Gson();
    }

    public static OkHttpUtils getInstance() {
        if (instance == null) {
            synchronized (OkHttpUtils.class) {
                if (instance == null) {
                    instance = new OkHttpUtils();
                }
            }
        }

        return instance;
    }

    /**
     * 对外提供的Get方法访问
     * @param url
     * @param callBack
     */
    public void Get(String url, MyCallBack callBack) {
        /**
         * 通过url和GET方式构建Request
         */
        Request request = bulidRequestForGet(url);
        /**
         * 请求网络的逻辑
         */
        requestNetWork(request, callBack);
    }

    /**
     * 对外提供的Post方法访问
     * @param url
     * @param parms: 提交内容为表单数据
     * @param callBack
     */
    public void PostWithFormData(String url, Map<String, String> parms, MyCallBack callBack) {
        /**
         * 通过url和POST方式构建Request
         */
        Request request = bulidRequestForPostByForm(url, parms);
        /**
         * 请求网络的逻辑
         */
        requestNetWork(request, callBack);

    }

    /**
     * 对外提供的Post方法访问
     * @param url
     * @param json: 提交内容为json数据
     * @param callBack
     */
    public void PostWithJson(String url, String json, MyCallBack callBack) {
        /**
         * 通过url和POST方式构建Request
         */
        Request request = bulidRequestForPostByJson(url, json);
        /**
         * 请求网络的逻辑
         */
        requestNetWork(request, callBack);

    }

    /**
     * POST方式构建Request {json}
     * @param url
     * @param json
     * @return
     */
    private Request bulidRequestForPostByJson(String url, String json) {
        RequestBody body = RequestBody.create(JSON, json);

        return new Request.Builder()
                .url(url)
                .post(body)
                .build();
    }

    /**
     * POST方式构建Request {Form}
     * @param url
     * @param parms
     * @return
     */
    private Request bulidRequestForPostByForm(String url, Map<String, String> parms) {

        FormBody.Builder builder = new FormBody.Builder();

        if (parms != null) {
            for (Map.Entry<String, String> entry :
                    parms.entrySet()) {
                builder.add(entry.getKey(), entry.getValue());
            }

        }
        FormBody body = builder.build();


        return new Request.Builder()
                .url(url)
                .post(body)
                .build();
    }


    /**
     * GET方式构建Request
     * @param url
     * @return
     */
    private Request bulidRequestForGet(String url) {

        return new Request.Builder()
                .url(url)
                .get()
                .build();
    }


    private void requestNetWork(Request request, MyCallBack<Object> callBack) {

        /**
         * 处理连网逻辑,此处只处理异步操作enqueue
         */
        callBack.onLoadingBefore(request);

        mOkHttpClient.newCall(request).enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                mHandler.post(() -> callBack.onFailure(request, e));

            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                if (response.isSuccessful()) {

                    String resultStr = response.body().string();
                    if (callBack.mType == String.class) {
                        // 如果想要返回字符串 直接返回就行
                        mHandler.post(() -> callBack.onSuccess(response, resultStr));
                    } else {
                        // 需要返回解析好的javaBean集合
                        try {
                            // 此处暂时写成object,使用时返回具体的带泛型的集合
                            Object obj = mGson.fromJson(resultStr, callBack.mType);
                            mHandler.post(() -> callBack.onSuccess(response, obj));
                        } catch (Exception e) {
                            // 解析错误时
                            mHandler.post(() -> callBack.onError(response));
                        }

                    }

                } else {
                    mHandler.post(() -> callBack.onError(response));
                }
            }
        });


    }


}
原文地址:https://www.cnblogs.com/xgjblog/p/10578502.html