zoukankan      html  css  js  c++  java
  • [转]OkHttp3 最有营养的初级教程

    一、前言

    自从Android4.4开始,google已经开始将源码中的HttpURLConnection替换为OkHttp,而在Android6.0之后的SDK中google更是移除了对于HttpClient的支持,而市面上流行的Retrofit同样是使用OkHttp进行再次封装而来的。由此看见学习OkHttp的重要性。

    本篇文章是以当前最新的版本 3.5.0为例(2.0及以上版本版本与3.0以上版本存在较大差异,本文不做深入讨论,请自行百度),使用Android Stuido作为开发环境,带领大家简单的熟悉OKHttp的使用情况。作为《Android网络编程》系类文章之一,后面的文章会围绕OKHttp3做逐渐深入的探讨。这篇文章我们要达到的目的就是:不深究,简单明了,可以直接粘贴复制。

    二、使用前的准备

    2.1 官方文档

    要知道学习一门新技术,最好的资料永远是官方文档:
    OkHttp官方介绍
    github源码

    2.2 Android Studio 配置gradle环境:

    compile 'com.squareup.okhttp3:okhttp:3.5.0'
    compile 'com.squareup.okio:okio:1.11.0'

    2.3 添加网络权限

    不要忘记添加权限啊,这也是常常被开发忽略的地方

    <uses-permission android:name="android.permission.INTERNET"/>

    三、使用教程

    3.1 Http Get

    3.1.1 异步的Get

    在Http请求中最常见的就是get方法了,在大多数的使用场景中,我们使用的都是异步的Get请求,下面我们就是用OkHttp的异步Get去请求一下百度的首页。

            // step 1: 创建 OkHttpClient 对象    
            OkHttpClient okHttpClient = new OkHttpClient();
    
            // step 2: 创建一个请求,不指定请求方法时默认是GET。
            Request.Builder requestBuilder = new Request.Builder().url("http://www.baidu.com");
            //可以省略,默认是GET请求
            requestBuilder.method("GET",null);
    
            // step 3:创建 Call 对象
            Call call = okHttpClient.newCall(requestBuilder.build());
    
            //step 4: 开始异步请求
            call.enqueue(new Callback() {
                @Override
                public void onFailure(Call call, IOException e) {
                    // TODO: 17-1-4  请求失败
                }
    
                @Override
                public void onResponse(Call call, Response response) throws IOException {
                    // TODO: 17-1-4 请求成功
                    //获得返回体
                    ResponseBody body = response.body();
                }
            });

    以上就是发送一个异步的Get请求的主要步骤。首先我们要创建一个OkHttpClickRequest.Builder()对象,再通过url()方法设置了网络地址来指定访问的目标,不仅如此 Request.Builder() 是支持链式编程的(返回体是本体)在这里可以设置这些方法哦:


    Request.Builder()链式编程,在此不做探讨

    接下来我们就要将OkHttpClick的对象与Request的对象建立起来联系,使用okHttpClicknewCall()方法得到一个Call对象,这个Call对象的作用就是相当于将请求封装成了一个任务,既然是任务,自然就会有execute()和cancel()等方法。

    最后,我们希望以异步的方式去执行请求,所以我们调用的是call.enqueue,将call加入调度队列,然后等待任务执行完成,我们在Callback中即可得到结果。但要注意的是,call的回调是子线程,所以是不能直接操作界面的。使用时需要自行处理。当请求成功时就会回调onResponse()方法,我们可以看到返回的结果是 Response对象,在此我们比较关注的是请求中的返回体bodyResponseBody类型),大多数的情况下我们希望获得字符串从而进行json解析获得数据,所以可以通过body.string()的方式获得字符串。


    ResponseBody 的 API


    查看ResponseBody的API文档可以看到,body还可以获取byte[]、Reader、InputStream,其中最惊奇一点就是可以返回InputStream,这至少说明了OkHttp是可以支持大文件的下载的,这样一来我们就可以轻松的使用InputStream进行I/O方式的文件写入啦!!!。

    让我们实现一下吧:

            //step 1: 不变的第一步创建 OkHttpClick
            OkHttpClient okHttpClient = new OkHttpClient();
    
            //step 2: 创建Requset
            Request request = new Request.Builder()
                    .url("http://www.ssyer.com/uploads/org_2017010593503_775.jpg")
                    .build();
    
            //step 3:建立联系,创建Call
            mOkHttpClient.newCall(request).enqueue(new Callback() {
                @Override
                public void onFailure(Call call, IOException e) {
                }
    
                @Override
                public void onResponse(Call call, Response response) {
                    InputStream inputStream = response.body().byteStream();
                    FileOutputStream fileOutputStream = null;
                    try {
                        File file = new File(Environment.getExternalStorageDirectory() + "大狮子.jpg");
                        fileOutputStream = new FileOutputStream(file);
                        byte[] buffer = new byte[2048];
                        int len = 0;
                        while ((len = inputStream.read(buffer)) != -1) {
                            fileOutputStream.write(buffer, 0, len);
                        }
                        fileOutputStream.flush();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
    
                    Log.d("downloadAsynFile", "文件下载成功");
                }
            });

    3.1.1 同步的Get

    当然Get也支持阻塞方式的同步请求,不过在开发中这种方法很少被使用。上面我们也说了Call有一个execute()方法,你也可以直接调用call.execute()返回一个Response。然后利用isSuccessful()判读是否成功,进行相应的结果解析。

    3.2 异步的Http Post

    在看过了Get请求方式,相信你对于请求的用法也用基本的掌握了,Post的使用使用方法和Get虽然存在些许差异,但是本质是不变的。那么下面就让我们以携带键值对的Post为例,先熟悉一下Post的使用方法吧。

    3.2.1 Post 上传键值对

            //step 1: 同样的需要创建一个OkHttpClick对象
            OkHttpClient okHttpClient = new OkHttpClient();
    
            //step 2: 创建  FormBody.Builder
            FormBody formBody = new FormBody.Builder()
                    .add("name", "dsd")
                    .build();
    
            //step 3: 创建请求
            Request request = new Request.Builder().url("http://www.baidu.com")
                    .post(formBody)
                    .build();
    
            //step 4: 建立联系 创建Call对象
            okHttpClient.newCall(request).enqueue(new Callback() {
                @Override
                public void onFailure(Call call, IOException e) {
                    // TODO: 17-1-4  请求失败
                }
    
                @Override
                public void onResponse(Call call, Response response) throws IOException {
                    // TODO: 17-1-4 请求成功
                }
            });

    是不是和Get很相似啊。大家都清楚,在使用Post的时候,参数是包含在请求体中的。所以我们通过FormBody,添加多个String键值对,然后为Request添加post(formBody)完成我们Request的构造。之后的步骤就和Get的步骤一样了,是不是很简单啊!

    3.2.2 Post异步上传文件

    直接上代码

           // step 1: 创建 OkHttpClient 对象
            OkHttpClient okHttpClient = new OkHttpClient();
    
            //step 2:创建 RequestBody 以及所需的参数
            //2.1 获取文件
            File file = new File(Environment.getExternalStorageDirectory() + "test.txt");
            //2.2 创建 MediaType 设置上传文件类型
            MediaType MEDIATYPE = MediaType.parse("text/plain; charset=utf-8");
            //2.3 获取请求体
            RequestBody requestBody = RequestBody.create(MEDIATYPE, file);
    
            //step 3:创建请求
            Request request = new Request.Builder().url("http://www.baidu.com")
                    .post(requestBody)
                    .build();
    
            //step 4 建立联系
            okHttpClient.newCall(request).enqueue(new Callback() {
                @Override
                public void onFailure(Call call, IOException e) {
                    // TODO: 17-1-4  请求失败
                }
    
                @Override
                public void onResponse(Call call, Response response) throws IOException {
                    // TODO: 17-1-4 请求成功
                }
            });

    当然这里需要添加权限滴,你是不是忘记了呢。

    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/> 
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

    第一步与之前都相同,但是从第二步开始就用了一定的差异了。在step2 中我们需要通过MediaType.parse("text/plain; charset=utf-8")为上传文件设置一定类型(MIME)在这里我们上传的纯文本文件所以选择"text/plain类型,而编码格式为utf-8。下面为大家列出常见的文件类型,方便使用。

    参数说明
    text/html HTML格式
    text/plain 纯文本格式
    text/xml XML格式
    image/gif gif图片格式
    image/jpeg jpg图片格式
    image/png png图片格式
    application/xhtml+xml XHTML格式
    application/xml XML数据格式
    application/atom+xml Atom XML聚合格式
    application/json JSON数据格式
    application/pdf pdf格式
    application/msword Word文档格式
    application/octet-stream 二进制流数据

    其实MIME文件类型特批多,有兴趣的朋友可以可参见w3school上的MIME 参考手册


    上传类型

    在创建RequestBody的时候可以看到,我们不仅仅可以上传File文件,还可以上传StringByteStringbyte数组等类型,其中上传byte数据时可以选择三个参数的creta方法,需要指定偏移量和需要写入的byte长度,哈哈这不是说明可以直接进行多线程、断点上传吗!通过这些类型,我们可以上传Json串,图片等内容真是方便又好用啊。

    总结

    经过上面的介绍我相信大家对OkHttp简单使用有了一定的了解,OkHttp3使用起来是不是很简单呢,但是每一次请求的步骤都有着大量重复的地方,这要是在实际开发中,还不把人累着啊,本着节约开(tou)发周(lan)期的目的,咳咳,后面的文章会进一步的带领大家学习OkHttp3的高级用法和OkHttp工具类的封装哦,敬请期待。

    参考:

    1. https://github.com/square/okhttp
    2. Android OkHttp完全解析 是时候来了解OkHttp了

    (原文地址:http://www.jianshu.com/p/7d88613c0b0f)

  • 相关阅读:
    flink 读取kafka 数据,partition分配
    Flink 报错 "Could not find a suitable table factory for 'org.apache.flink.table.factories.StreamTableSourceFactory' in the classpath"
    flume接收http请求,并将数据写到kafka
    【翻译】Flume 1.8.0 User Guide(用户指南) Processors
    【翻译】Flume 1.8.0 User Guide(用户指南) Channel
    【翻译】Flume 1.8.0 User Guide(用户指南) Sink
    【翻译】Flume 1.8.0 User Guide(用户指南) source
    【翻译】Flume 1.8.0 User Guide(用户指南)
    Apache Flink 简单安装
    Java之使用IDE
  • 原文地址:https://www.cnblogs.com/jianyungsun/p/6648390.html
Copyright © 2011-2022 走看看