转载请标明出处:
http://blog.csdn.net/lmj623565791/article/details/49734867
本文出自:【张鸿洋的博客】

一、概述

之前写了篇Android OkHttp全然解析 是时候来了解OkHttp了,事实上主要是作为okhttp的普及文章,当然里面也简单封装了工具类,没想到关注和使用的人还挺多的,因为这股热情,该工具类中的方法也是剧增,各种重载方法,以致于使用起来极不方便。实在羞愧。

于是,在这个周末,抽点时间对该工具类,进行了又一次的拆解与编写。顺便完好下功能,尽可能的提升其使用起来的方便性和易扩展性。

标题的改善,也是指的是对于我之前的代码进行改善。

假设你对okhttp不了解,能够通过Android OkHttp全然解析 是时候来了解OkHttp了进行了解。

ok。那么眼下,该封装库志支持:

  • 一般的get请求
  • 一般的post请求
  • 基于Http的文件上传
  • 文件下载
  • 上传下载的进度回调
  • 载入图片
  • 支持请求回调。直接返回对象、对象集合
  • 支持session的保持
  • 支持自签名站点https的訪问,提供方法设置下证书就可以
  • 支持取消某个请求

源代码地址:https://github.com/hongyangAndroid/okhttp-utils


引入:

  • Android Studio

    使用前。对于Android Studio的用户。能够选择加入:

    compile project(':okhttputils')

    或者

    compile 'com.zhy:okhttputils:2.0.0'
  • Eclipse

    自行copy源代码。

二、基本使用方法

眼下基本的使用方法格式为:

OkHttpUtils
    .get()
    .url(url)
    .addParams("username", "hyman")
    .addParams("password", "123")
    .build()
    .execute(callback);

通过链式去依据自己的须要加入各种參数,最后调用execute(callback)进行运行,传入callback则代表是异步。假设单纯的execute()则代表同步的方法调用。

能够看到,取消了之前一堆的get重载方法。參数也能够进行灵活的选择了。

以下简单看一下,全部的使用方法:

(1)GET请求

String url = "http://www.csdn.net/";
OkHttpUtils
    .get()
    .url(url)
    .addParams("username", "hyman")
    .addParams("password", "123")
    .build()
    .execute(new StringCallback()
            {
                @Override
                public void onError(Request request, Exception e)
                {

                }

                @Override
                public void onResponse(String response)
                {

                }
            });

(2)POST请求

 OkHttpUtils
    .post()
    .url(url)
    .addParams("username", "hyman")
    .addParams("password", "123")
    .build()
    .execute(callback);

(3)Post String

OkHttpUtils
    .postString()
    .url(url)
    .content(new Gson().toJson(new User("zhy", "123")))
    .build()
    .execute(new MyStringCallback());   

将string作为请求体传入到服务端,比如json字符串。

(4)Post File

OkHttpUtils
    .postFile()
    .url(url)
    .file(file)
    .build()
    .execute(new MyStringCallback());

将file作为请求体传入到服务端.

(5)基于POST的文件上传(相似web上的表单)

OkHttpUtils.post()//
    .addFile("mFile", "messenger_01.png", file)//
    .addFile("mFile", "test1.txt", file2)//
    .url(url)
    .params(params)//
    .headers(headers)//
    .build()//
    .execute(new MyStringCallback());

(6)下载文件

OkHttpUtils//
    .get()//
    .url(url)//
    .build()//
    .execute(new FileCallBack(Environment.getExternalStorageDirectory().getAbsolutePath(), "gson-2.2.1.jar")//
    {
        @Override
        public void inProgress(float progress)
        {
            mProgressBar.setProgress((int) (100 * progress));
        }

        @Override
        public void onError(Request request, Exception e)
        {
            Log.e(TAG, "onError :" + e.getMessage());
        }

        @Override
        public void onResponse(File file)
        {
            Log.e(TAG, "onResponse :" + file.getAbsolutePath());
        }
    });

(7)显示图片

OkHttpUtils
    .get()//
    .url(url)//
    .build()//
    .execute(new BitmapCallback()
    {
        @Override
        public void onError(Request request, Exception e)
        {
            mTv.setText("onError:" + e.getMessage());
        }

        @Override
        public void onResponse(Bitmap bitmap)
        {
            mImageView.setImageBitmap(bitmap);
        }
    });

哈,眼下来看。清晰多了。

三、对于上传下载的回调

new Callback<?>()
{
    //...
    @Override
    public void inProgress(float progress)
    {
       //use progress: 0 ~ 1
    }
}

对于传入的callback有个inProgress方法,须要拿到进度直接复写该方法就可以。

四、对于自己主动解析为实体类

眼下去除了Gson的依赖,提供了自己定义Callback的方式,让用户自己去解析返回的数据,眼下提供了StringCallbackFileCallback,BitmapCallback 分别用于返回string。文件下载,载入图片。

当然假设你希望解析为对象,你能够:

public abstract class UserCallback extends Callback<User>
{
    //非UI线程,支持不论什么耗时操作
    @Override
    public User parseNetworkResponse(Response response) throws IOException
    {
        String string = response.body().string();
        User user = new Gson().fromJson(string, User.class);
        return user;
    }
}

自己使用自己喜欢的Json解析库完毕就可以。

解析成List<User>,则例如以下:

public abstract class ListUserCallback extends Callback<List<User>>
{
    @Override
    public List<User> parseNetworkResponse(Response response) throws IOException
    {
        String string = response.body().string();
        List<User> user = new Gson().fromJson(string, List.class);
        return user;
    }


}

五、对于https单向认证

很easy,拿到xxx.cert的证书。

然后调用


OkHttpUtils.getInstance()
        .setCertificates(inputstream);

建议使用方式,比如我的证书放在assets文件夹:


/**
 * Created by zhy on 15/8/25.
 */
public class MyApplication extends Application
{
    @Override
    public void onCreate()
    {
        super.onCreate();

        try
        {    
        OkHttpUtils
         .getInstance()
         .setCertificates(getAssets().open("aaa.cer"),
 getAssets().open("server.cer"));
        } catch (IOException e)
        {
            e.printStackTrace();
        }
    }
}

就可以。别忘了注冊Application。

注意:假设https站点为权威机构颁发的证书,不须要以上设置。自签名的证书才须要。

六、配置

(1)全局配置

能够在Application中。通过:

OkHttpClient client = 
OkHttpUtils.getInstance().getOkHttpClient();

然后调用client的各种set方法。

比如:

client.setConnectTimeout(100000, TimeUnit.MILLISECONDS);

(2)为单个请求设置超时

比方涉及到文件的须要设置读写等待时间多一点。

 OkHttpUtils
    .get()//
    .url(url)//
    .tag(this)//
    .build()//
    .connTimeOut(20000)
    .readTimeOut(20000)
    .writeTimeOut(20000)
    .execute()

调用build()之后。能够随即设置各种timeOut.

(3)取消单个请求

 RequestCall call = OkHttpUtils.get().url(url).build();
 call.cancel();

(4)依据tag取消请求

眼下对于支持的方法都加入了最后一个參数Object tag,取消则通过OkHttpUtils.cancelTag(tag)运行。

比如:在Activity中,当Activity销毁取消请求:

OkHttpUtils
    .get()//
    .url(url)//
    .tag(this)//
    .build()//

@Override
protected void onDestroy()
{
    super.onDestroy();
    //能够取消同一个tag的
    OkHttpUtils.cancelTag(this);//取消以Activity.this作为tag的请求
}

比方,当前Activity页面全部的请求以Activity对象作为tag。能够在onDestory里面统一取消。

七、浅谈封装

事实上整个封装的过程比較简单,这里简单描写叙述下,对于okhttp一个请求的流程大致是这种:

//创建okHttpClient对象
OkHttpClient mOkHttpClient = new OkHttpClient();
//创建一个Request
final Request request = new Request.Builder()
                .url("https://github.com/hongyangAndroid")
                .build();
//new call
Call call = mOkHttpClient.newCall(request); 
//请求加入调度
call.enqueue(new Callback()
{
    @Override
    public void onFailure(Request request, IOException e)
    {
    }

    @Override
    public void onResponse(final Response response) throws IOException
    {
            //String htmlStr =  response.body().string();
    }
});             

当中基本的差异,事实上就是request的构建过程。

我对Request抽象了一个类:OkHttpRequest

public abstract class OkHttpRequest
{
    protected RequestBody requestBody;
    protected Request request;

    protected String url;
    protected String tag;
    protected Map<String, String> params;
    protected Map<String, String> headers;

    protected OkHttpRequest(String url, String tag,
                            Map<String, String> params, Map<String, String> headers)
    {
        this.url = url;
        this.tag = tag;
        this.params = params;
        this.headers = headers;
    }

    protected abstract Request buildRequest();
    protected abstract RequestBody buildRequestBody();

    protected void prepareInvoked(ResultCallback callback)
    {
        requestBody = buildRequestBody();
        requestBody = wrapRequestBody(requestBody, callback);
        request = buildRequest();
    }

    protected RequestBody wrapRequestBody(RequestBody requestBody, final ResultCallback callback)
    {
        return requestBody;
    }


    public void invokeAsyn(ResultCallback callback)
    {
        prepareInvoked(callback);
        mOkHttpClientManager.execute(request, callback);
    }


     // other common methods
 }   

一个request的构建呢,我分三个步骤:buildRequestBody , wrapRequestBody ,buildRequest这种次序,当以上三个方法没有问题时,我们就拿到了request。然后运行就可以。

可是对于不同的请求。requestBody以及request的构建过程是不同的。所以大家能够看到buildRequestBody ,buildRequest为抽象的方法,也就是不同的请求类。比方OkHttpGetRequestOkHttpPostRequest等须要自己去构建自己的request。

对于wrapRequestBody方法呢,能够看到它默认基本属于空实现,主要是因为并不是全部的请求类都须要复写它,仅仅有上传的时候呢,须要回调进度。须要对requestBody进行包装。所以这种方法相似于一个钩子。

事实上这个过程有点相似模板方法模式,有兴趣能够看看一个短篇介绍设计模式 模版方法模式 展现程序猿的一天 .

对于更加具体的使用方法,能够查看github上面的readme。以及demo,眼下demo包括:

对于上传文件的两个button,须要自己搭建服务器。其它的button能够直接測试。

最后,因为本人水平有限。以及时间比較仓促~~发现问题,欢迎提issue,我会抽时间解决。 have a nice day ~

源代码点击下载


欢迎关注我的微博:
http://weibo.com/u/3165018720


群号:514447580,欢迎入群

微信公众号:hongyangAndroid
(欢迎关注,第一时间推送博文信息)