当前位置: 移动技术网 > IT编程>移动开发>Android > 网络通讯库OkHttp精炼详解

网络通讯库OkHttp精炼详解

2018年09月18日  | 移动技术网IT编程  | 我要评论

最新电影有哪些,路桥中学,武夷山东站

安卓发展的初期阶段,为测试安卓网络响应的功能,一群美国的安卓工程师跑到了网普遍不好的非洲,在那里弱网的情况下,试用应用程序。然后根据当地的实际情况,这群安卓工程师编写了出了这个非常有名的网络通讯库——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("https://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("https://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("https://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("https://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,瞬间被其简洁的代码,连贯的逻辑吸引了。

如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复

相关文章:

验证码:
移动技术网