网络通讯库OkHttp精炼详解

安卓发展的初期阶段,为测试安卓网络响应的功能,一群美国的安卓工程师跑到了网普遍不好的非洲,在那里弱网的情况下,试用应用程序。然后根据当地的实际情况,这群安卓工程师编写了出了这个非常有名的网络通讯库——OkHttp,专门用来解决弱网情景下的应用程序联网问题,取得了非常好的反响。

一、前期基础知识储备

为什么需要一个HTTP库?

(1)HttpURLConnection非常弱

起初Android系统提供了两种HTTP通信类,HttpURLConnection和HttpClient。后来谷歌在6.0版本删除了HttpClient相关API,所以Google在大部分安卓版本中推荐使用HttpURLConnection,但是这个类相比HttpClient实在是繁琐难用

(2)OkHttp非常强大

后来移动支付Square公司贡献了OkHttp这一安卓最受欢迎的轻量级级框架,用于为广大开发者提供更好的网络请求方式。(Square还贡献了Retrofit/Picasso/LeakCanary)

OkHttp是一个相对成熟的网络请求解决方案, Android4.4的源码中可以看到HttpURLConnection已经替换成OkHttp实现了。所以我们更有理由相信OkHttp的强大。实际写过HttpURLConnection的人都知道多么麻烦!侧面对比一下,就懂了。

二、上代码 具体实现

build.gradle文件添加依赖

compile ‘com.squareup.okhttp3:okhttp:3.4.1’

okhttp的简单使用,主要包含:

  • 一般的get请求
  • 一般的post请求
  • 基于Http的文件上传
  • 文件下载

(1)实现一次OkHttp网络请求

简单实现一次OkHttp类型的网络请求分四步走:

    1)创建OkHttpClient实例;

    2)创建一个Request对象;

    3)创建一个Call对象;

    4)同步/异步发送网络请求

具体代码如下:

OkHttpClient client = new OkHttpClient();//创建OkHttpClient实例
Request request = new Request
		.url("http://baidu.com");
		.build(); //如果想要发起一条Http请求,首先需要创建一个Request对象
		//调用OkHttpClient的newCall()方法来创建一个Call对象,并调用它的execute()方法发送请求|并获取服务器返回的数据		  
	        Response response = client.newCall(request).execute; 
               String responseData = response.body().string();

注意,这里Response对象就是服务器返回的数据,使用response.body().string()得到具体返回的内容,这里得到是字符类型;如果希望获得返回的二进制字节数组,则调用response.body().bytes();如果你想拿到返回的inputStream,则调用response.body().byteStream()。在得到的返回内容之后再调用XML/JSON解析方法进行解析返回数据的解析。

同时,还需注意,①OkHttp官方文档并不建议我们创建多个OkHttpClient,因此全局使用一个。 如果有需要,可以使用clone方法,再进行自定义;②执行网络请求的方法. execute只能执行一次。

以上实现的是GET同步请求,实现GET异步请求,只需要调用enqueue()方法即可,把这个请求,加入到队列当中,代码如下:

client.newCall(request).enqueue(new Callback() {
        @Override
        public void onFailure(Call call, IOException e) {
        }
        @Override
        public void onResponse(Call call, Response response) throws IOException {
            if(response.isSuccessful()){//回调的方法执行在子线程。
                //数据请求成功的处理
            }
        }
    });

注:同步的请求方式,需要单独开启线程;而异步的网络线程不需要单独开启线程,逻辑会在enqueue()方法中调用好,但注意两种请求方式都不是在主线程中发生的,后面涉及到UI操作的都要返回到主线程中实现相关操作。

private void showResponse(final String response) {
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                // 在这里进行UI操作,将结果显示到界面上
                responseText.setText(response);
            }
        });	

(2)实现POST类型的网络请求

如果是发起一条POST请求会比GET请求稍微复杂一点,我们需要先构建出一个RequestBody对象用来存放待提交的餐具,而根据待提交的参数不同,又会有不同种类的RequestBody对象。

下面我们看一下Request.Builder类的post方法的声明:

public Builder post(RequestBody body)

由PSOT方法的声明可以看出,post方法接收的参数是RequestBody 对象,所以只要是RequestBody 类以及子类对象都可以当作参数进行传递。在开发中,我们可以直接使用的RequestBody对象有三种:

1)FormBody——传递键值对参数

这种方式用来上传String类型的键值对

private void postDataWithParame() {
    OkHttpClient client = new OkHttpClient();//创建OkHttpClient对象。
    FormBody.Builder formBody = new FormBody.Builder();//创建表单请求体
    formBody.add("username","zhangsan");//传递键值对参数
    Request request = new Request.Builder()//创建Request 对象。
            .url("http://www.baidu.com")
            .post(formBody.build())//传递请求体
            .build();
    client.newCall(request).enqueue(new Callback() {。。。});//此处省略回调方法。
}

2)RequestBody——上传Json或File对象

RequestBody是抽象类,故不能直接使用,但是他有静态方法create,使用这个方法可以得到RequestBody对象。这种方式可以上传Json对象或File对象

上传json对象使用示例如下:

OkHttpClient client = new OkHttpClient();//创建OkHttpClient对象。
MediaType JSON = MediaType.parse("application/json; charset=utf-8");//数据类型为json格式,
String jsonStr = "{\"username\":\"lisi\",\"nickname\":\"李四\"}";//json数据.
RequestBody body = RequestBody.create(JSON, josnStr);
Request request = new Request.Builder()
        .url("http://www.baidu.com")
        .post(body)
        .build();
client.newCall(request).enqueue(new Callback() {。。。});//此处省略回调方法。	

上传File对象使用示例如下:

OkHttpClient client = new OkHttpClient();//创建OkHttpClient对象。
MediaType fileType = MediaType.parse("File/*");//数据类型为json格式,
File file = new File("path");//file对象.
RequestBody body = RequestBody.create(fileType , file );
Request request = new Request.Builder()
        .url("http://www.baidu.com")
        .post(body)
        .build();
client.newCall(request).enqueue(new Callback() {。。。});//此处省略回调方法。

3)MultipartBody——同时传递键值对参数和File对象

这个字面意思是多重的body。我们知道FromBody传递的是字符串型的键值对,RequestBody传递的是多媒体,那么如果我们想二者都传递怎么办?此时就需要使用MultipartBody类。

OkHttpClient client = new OkHttpClient();
MultipartBody multipartBody =new MultipartBody.Builder()
        .setType(MultipartBody.FORM)
        .addFormDataPart("groupId",""+groupId)//添加键值对参数
        .addFormDataPart("title","title")
        .addFormDataPart("file",file.getName(),RequestBody.create(MediaType.parse("file/*"), file))//添加文件
        .build();
final Request request = new Request.Builder()
        .url(URLContant.CHAT_ROOM_SUBJECT_IMAGE)
        .post(multipartBody)
        .build();
client.newCall(request).enqueue(new Callback() {。。。});

(3)利用OkHttp返回的流对象进行下载文件

在OKHttp中并没有提供下载文件的功能,但是在Response中可以获取流对象,有了流对象我们就可以自己实现文件的下载。代码如下:

这段代码写在回调接口CallBack的onResponse方法中:

try{
    InputStream  is = response.body().byteStream();//从服务器得到输入流对象
    long sum = 0;
    File dir = new File(mDestFileDir);
    if (!dir.exists()){
        dir.mkdirs();
    }
    File file = new File(dir, mdestFileName);//根据目录和文件名得到file对象
    FileOutputStream  fos = new FileOutputStream(file);
    byte[] buf = new byte[1024*8];
    int len = 0;
    while ((len = is.read(buf)) != -1){
        fos.write(buf, 0, len);
    }
    fos.flush();
    return file;

}

(4)对于OKHttp的使用封装

由于okhttp是偏底层的网络请求类库,返回结果的回调方法仍然执行在子线程中,需要自己跳转到UI线程,使用麻烦。为了使用方便需要对OKHttp进行再次封装。对于OKHttp的封装首推的就是hongyang大神的OKHttpUtils

该封装库支持:

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

 

总结:笔者之前写过四篇网络通讯库类型的文章,分别介绍了VolleyRetrofit,在其中也穿插的介绍了Volley、Retrofit和OkHttp的各自优劣。其实笔者最开始接触到的网络框架是OkHttp,当时正在研究Android提供的原生HTTPURLConnection的网络请求方式,学的真的是快失去信心,没有系统的学习过Http协议,然后学习起HTTPURLConnection真的是很难,最起码过程很漫长,后来接触到了OkHttp,瞬间被其简洁的代码,连贯的逻辑吸引了。所以现在,写这一篇OkHttp的文章用来和大家一起分享。

 

 文章的最后分享几个链接,供读者参考:

OkHttp官网网址:OKHttp官网

了解源码可以在github上下载,地址是:https://github.com/square/okhttp

泡在网上的日子《OkHttp使用教程》

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值