博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Android架构系列-封装自己的okhttp
阅读量:7059 次
发布时间:2019-06-28

本文共 5588 字,大约阅读时间需要 18 分钟。

本文简述了为什么选择okhttp作为自己的项目网络库,和如何二次封装为module便于使用

注:进阶版MyOkHttp见文章:

0 Android架构系列文章

该系列文章会不断更新Android项目开发中一些好的架构和小技巧

系列一

系列二
系列三
系列四
系列五

1 网络库的选择和为什么放弃retrofit

本来项目的网络库选择的搭配是最流行的retrofit+okhttp+gson.如下图版本库里还有记录。

版本记录

But!后来遇到了这样的问题:服务端提供的API无法遵循Restful的API格式,而且不同模块由于分服务开发的,也不能保证格式一致。导致API接口层的实现十分牵强。最终api层的编写不能专注于业务,适得其反。(最起码现在的服务端还不适合与retrofit的使用)

最后决定放弃使用retrofit,使用自己二次封装的okhttp。

2 封装使用okhttp

封装过程中参考了:

hongyang的

赵凯强的

2.1 怎么使用

先说封装好的okhttp+gson如何使用。(封装了POST请求,GET请求,上传文件,下载文件,取消请求和Gson转换等功能)

2.1.1 POST请求

Map
params = new HashMap
();params.put("name", "tsy");MyOkHttp.get().post(this, "http://192.168.3.1/test_okhttp.php", params, new JsonResponseHandler() { @Override public void onSuccess(int statusCode, JSONObject response) { LogUtils.v(TAG, statusCode + " " + response); } @Override public void onFailure(int statusCode, String error_msg) { LogUtils.v(TAG, statusCode + " " + error_msg); }});复制代码

2.1.2 GET请求

Map
params = new HashMap
();params.put("name", "tsy");MyOkHttp.get().get(this, "http://192.168.3.1/test_okhttp.php", params, new RawResponseHandler() { @Override public void onSuccess(int statusCode, String response) { LogUtils.v(TAG, statusCode + " " + response); } @Override public void onFailure(int statusCode, String error_msg) { LogUtils.v(TAG, statusCode + " " + error_msg); }});复制代码

2.1.3 上传文件

Map
params = new HashMap
();params.put("name", "tsy");Map
files = new HashMap
();File file = new File(Environment.getExternalStorageDirectory() + "/com.ci123.service.splashandroid/splash/1.png");files.put("avatar", file);MyOkHttp.get().upload(this, "http://192.168.3.1/test_post.php", params, files, new GsonResponseHandler
() { @Override public void onFailure(int statusCode, String error_msg) { LogUtils.v(TAG, statusCode + " " + error_msg); } @Override public void onSuccess(int statusCode, BB response) { LogUtils.v(TAG, statusCode + " " + response.ret); } @Override public void onProgress(long currentBytes, long totalBytes) { LogUtils.v(TAG, currentBytes + "/" + totalBytes); }});复制代码

2.1.4 下载文件

MyOkHttp.get().download(this, "http://192.168.3.1/output_tmp.jpg",        Environment.getExternalStorageDirectory() + "/com.tsy.splashandroid/", "1.jpg",        new DownloadResponseHandler() {    @Override    public void onFinish(File download_file) {        LogUtils.v(TAG, "onFinish:" + download_file.getPath());    }    @Override    public void onProgress(long currentBytes, long totalBytes) {        LogUtils.v(TAG, currentBytes + "/" + totalBytes);    }    @Override    public void onFailure(String error_msg) {        LogUtils.v(TAG, error_msg);    }});复制代码

2.1.5 取消请求(建议放在BaseActivity,BaseFragment的onDestroy中)

MyOkHttp.get().cancel(this);复制代码

2.1.6 返回格式

post,get,upload3个接口可以选择返回格式为普通Json还是Gson

  1. 普通json

    回调继承JsonResponseHandler,例如POST请求的例子

  2. gson

    回调继承GsonResponseHandler,并设置泛型T,例如Upload请求的例子

  3. raw原始数据

    回调继承RawResponseHandler,例如GET请求例子

2.2 源码解析

源码集成在了BaseAndroidProject中作为网络底层模块,以module方式封装。其他项目可以直接module拿过来引入项目即可使用。

BaseAndroidProject的Github地址:

源码API入口在MyOkhttp文件中。POST请求和GET请求的实现很简单。在这我主要说明如何封装gson response和上传下载的进度监听。

2.2.1 gson返回封装

gson最后封装成了如下的使用形式:

MyOkHttp.get().post(this, "http://192.168.3.1/test_okhttp.php", params, new GsonResponseHandler
() { @Override public void onFailure(int statusCode, String error_msg) { LogUtils.v(TAG, statusCode + " " + error_msg); } @Override public void onSuccess(int statusCode, BB response) { LogUtils.v(TAG, statusCode + " " + response.ret); }});复制代码

gson response与普通json返回不同的是,在GsonResponseHandler的构造函数中使用反射机制动态获取到了本身的泛型类型,然后将该泛型类型转化为了Gson可以使用的Type保存起来。这样在结果回调时就可以使用该Type转为Gson。

public abstract class GsonResponseHandler
implements IResponseHandler { Type mType; public GsonResponseHandler() { Type myclass = getClass().getGenericSuperclass(); //反射获取带泛型的class if (myclass instanceof Class) { throw new RuntimeException("Missing type parameter."); } ParameterizedType parameter = (ParameterizedType) myclass; //获取所有泛型 mType = $Gson$Types.canonicalize(parameter.getActualTypeArguments()[0]); //将泛型转为type } public final Type getType() { return mType; } public abstract void onSuccess(int statusCode, T response); @Override public void onProgress(long currentBytes, long totalBytes) { }}复制代码

然后在okhttp获得到response后,判断到responseHandler是gson,就将结果转为gson格式。

if(mResponseHandler instanceof JsonResponseHandler) {    ...} else if(mResponseHandler instanceof GsonResponseHandler) {    mHandler.post(new Runnable() {        @Override        public void run() {            try {                Gson gson = new Gson();                ((GsonResponseHandler)mResponseHandler).onSuccess(response.code(),                        gson.fromJson(response_body, ((GsonResponseHandler)mResponseHandler).getType()));            } catch (Exception e) {                LogUtils.e("onResponse fail parse gson, body=" + response_body, e);                mResponseHandler.onFailure(response.code(), "fail parse gson, body=" + response_body);            }        }    });}复制代码

2.2.2 上传和下载的监听进度

该部分参考了赵凯强的-开源项目OkHttpPlus 里面说明的比较清楚。大概的原理就是使用okio分别重写requestbody和responsebody,在body中设置进度监听返回。just so so。详细原理可以直接跳转博客进行学习啊,在这就不重新造轮子了。

3 结尾

最终,okhttp被我封装为了一个module,在这个module中就会引入gson和okhttp了,所以不把它导出为jar包。以后的网络底层库就用这个module啦!

目录结构

更多文章关注我的公众号

我的公众号

转载地址:http://cdfll.baihongyu.com/

你可能感兴趣的文章
django的分页--不全也未实现
查看>>
html5 header和group
查看>>
WordPress博客网站fonts.useso加载慢解决办法
查看>>
卡特尔、辛迪加、托拉斯、康采恩有什么区别
查看>>
【python】SQLAlchemy
查看>>
spring @import和@importResource
查看>>
C语言中的main函数以及main函数是如何被调用的
查看>>
java-request与response编码问题
查看>>
NEL程序员专用轻钱包 进入0.01状态了
查看>>
【Java多线程】线程池学习
查看>>
性能优化系列七:SQL优化
查看>>
免费SD卡数据恢复工具哪里有
查看>>
fatal error LNK1169: 找到一个或多个多重定义的符号或多个.c/.cpp文件想同时调用定义在.h文件里面的全局变量,防止重定义变量问题。...
查看>>
【TCP ZeroWindow】与【TCP window Full】
查看>>
关于IE7 IE8兼容HTML5和CSS3的一种解决方案 (转)
查看>>
使用ASP.NET AJAX异步调用Web Service和页面中的类方法(4):异步通讯层生成的客户端代理类、使用HTTP GET进行调用...
查看>>
use komodo edit programming c
查看>>
Java数据库接口JDBC入门基础讲座_JDBC基础教程之驱动设置
查看>>
Python自然语言处理学习笔记(41):5.2 标注语料库
查看>>
MYSQL复制表
查看>>