OkHttp3 最有营养的初级教程,快来围观吧

TracyXZYV 8年前
   <p><img src="https://simg.open-open.com/show/a57bac9d8ccf8825c2b548ce69f095fe.jpg"></p>    <h2>一、前言</h2>    <p>自从Android4.4开始,google已经开始将源码中的HttpURLConnection替换为OkHttp,而在Android6.0之后的SDK中google更是移除了对于HttpClient的支持,而市面上流行的Retrofit同样是使用OkHttp进行再次封装而来的。由此看见学习OkHttp的重要性。</p>    <p>本篇文章是以当前最新的版本 3.5.0为例(2.0及以上版本版本与3.0以上版本存在较大差异,本文不做深入讨论,请自行百度),使用Android Stuido作为开发环境,带领大家简单的熟悉OKHttp的使用情况。作为《Android网络编程》系类文章之一,后面的文章会围绕OKHttp3做逐渐深入的探讨。这篇文章我们要达到的 <strong>目的就是:不深究,简单明了,可以直接粘贴复制。</strong></p>    <h2>二、使用前的准备</h2>    <h2>2.1 官方文档</h2>    <p>要知道学习一门新技术,最好的资料永远是官方文档:</p>    <p><a href="/misc/goto?guid=4958860115824511695" rel="nofollow,noindex">OkHttp官方介绍</a></p>    <p><a href="/misc/goto?guid=4958964956476581901" rel="nofollow,noindex">github源码</a></p>    <h2>2.2 Android Studio 配置gradle环境:</h2>    <pre>  <code class="language-java">compile 'com.squareup.okhttp3:okhttp:3.5.0'  compile 'com.squareup.okio:okio:1.11.0'</code></pre>    <h2>2.3 添加网络权限</h2>    <p>不要忘记添加权限啊,这也是常常被开发忽略的地方</p>    <pre>  <code class="language-java"><uses-permission android:name="android.permission.INTERNET"/></code></pre>    <h2>三、使用教程</h2>    <h2>3.1 Http Get</h2>    <h3>3.1.1 异步的Get</h3>    <p>在Http请求中最常见的就是get方法了,在大多数的使用场景中,我们使用的都是异步的Get请求,下面我们就是用OkHttp的异步Get去请求一下百度的首页。</p>    <pre>  <code class="language-java">// 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();              }          });</code></pre>    <p>以上就是发送一个异步的Get请求的主要步骤。首先我们要创建一个 OkHttpClick 和 Request.Builder() 对象,再通过 url() 方法设置了网络地址来指定访问的目标,不仅如此 Request.Builder() 是支持链式编程的(返回体是本体)在这里可以设置这些方法哦:</p>    <p style="text-align:center"><img src="https://simg.open-open.com/show/25b7eb886b79e41b291f92847ae98f12.png"></p>    <p>Request.Builder()链式编程,在此不做探讨</p>    <p>接下来我们就要将 OkHttpClick 的对象与 Request 的对象建立起来联系,使用 okHttpClick 的 newCall() 方法得到一个 Call 对象,这个Call对象的作用就是相当于将请求封装成了一个任务,既然是任务,自然就会有execute()和cancel()等方法。</p>    <p>最后,我们希望以异步的方式去执行请求,所以我们调用的是call.enqueue,将call加入调度队列,然后等待任务执行完成,我们在Callback中即可得到结果。 <em>但要注意的是,call的回调是子线程,所以是不能直接操作界面的。使用时需要自行处理</em> 。当请求成功时就会回调 onResponse() 方法,我们可以看到返回的结果是 Response 对象,在此我们比较关注的是请求中的返回体 body ( ResponseBody 类型),大多数的情况下我们希望获得字符串从而进行json解析获得数据,所以可以通过 body.string() 的方式获得字符串。</p>    <p><img src="https://simg.open-open.com/show/9f61d7beaca430cf03b408886bfbc957.png"></p>    <p>ResponseBody 的 API</p>    <p>查看 ResponseBody 的API文档可以看到, body 还可以获取byte[]、Reader、InputStream,其中最惊奇一点就是可以返回InputStream,这至少说明了OkHttp是可以支持大文件的下载的,这样一来我们就可以轻松的使用InputStream进行I/O方式的文件写入啦!!!。</p>    <p>让我们实现一下吧:</p>    <pre>  <code class="language-java">//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", "文件下载成功");              }          });</code></pre>    <h3>3.1.1 同步的Get</h3>    <p>当然 Get 也支持阻塞方式的同步请求,不过在开发中这种方法很少被使用。上面我们也说了Call有一个 execute() 方法,你也可以直接调用 call.execute() 返回一个 Response 。然后利用 isSuccessful() 判读是否成功,进行相应的结果解析。</p>    <h2>3.2 异步的Http Post</h2>    <p>在看过了 Get 请求方式,相信你对于请求的用法也用基本的掌握了, Post 的使用使用方法和 Get 虽然存在些许差异,但是本质是不变的。那么下面就让我们以携带键值对的 Post 为例,先熟悉一下 Post 的使用方法吧。</p>    <h3>3.2.1 Post 上传键值对</h3>    <pre>  <code class="language-java">//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 请求成功              }          });</code></pre>    <p>是不是和 Get 很相似啊。大家都清楚,在使用 Post 的时候,参数是包含在请求体中的。所以我们通过 FormBody ,添加多个String键值对,然后为 Request 添加 post(formBody) 完成我们 Request 的构造。之后的步骤就和Get的步骤一样了,是不是很简单啊!</p>    <h3>3.2.2 Post异步上传文件</h3>    <p>直接上代码</p>    <pre>  <code class="language-java">// 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 请求成功              }          });</code></pre>    <p>当然这里需要添加权限滴,你是不是忘记了呢。</p>    <pre>  <code class="language-java"><uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>   <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/></code></pre>    <p>第一步与之前都相同,但是从第二步开始就用了一定的差异了。在step2 中我们需要通过 MediaType.parse("text/plain; charset=utf-8") 为上传文件设置一定类型(MIME)在这里我们上传的纯文本文件所以选择 "text/plain 类型,而编码格式为 utf-8 。下面为大家列出常见的文件类型,方便使用。</p>    <table>     <thead>      <tr>       <th>参数</th>       <th>说明</th>      </tr>     </thead>     <tbody>      <tr>       <td>text/html</td>       <td>HTML格式</td>      </tr>      <tr>       <td>text/plain</td>       <td>纯文本格式</td>      </tr>      <tr>       <td>text/xml</td>       <td>XML格式</td>      </tr>      <tr>       <td>image/gif</td>       <td>gif图片格式</td>      </tr>      <tr>       <td>image/jpeg</td>       <td>jpg图片格式</td>      </tr>      <tr>       <td>image/png</td>       <td>png图片格式</td>      </tr>      <tr>       <td>application/xhtml+xml</td>       <td>XHTML格式</td>      </tr>      <tr>       <td>application/xml</td>       <td>XML数据格式</td>      </tr>      <tr>       <td>application/atom+xml</td>       <td>Atom XML聚合格式</td>      </tr>      <tr>       <td>application/json</td>       <td>JSON数据格式</td>      </tr>      <tr>       <td>application/pdf</td>       <td>pdf格式</td>      </tr>      <tr>       <td>application/msword</td>       <td>Word文档格式</td>      </tr>      <tr>       <td>application/octet-stream</td>       <td>二进制流数据</td>      </tr>     </tbody>    </table>    <p style="text-align:center"><img src="https://simg.open-open.com/show/485437ab3e574ddfa2376c98cedc1a1c.png"></p>    <p>上传类型</p>    <p>在创建 RequestBody 的时候可以看到,我们不仅仅可以上传File文件,还可以上传 String , ByteString , byte 数组等类型,其中上传byte数据时可以选择三个参数的creta方法,需要指定偏移量和需要写入的byte长度,哈哈这不是说明可以直接 <strong>进行多线程、断点上传</strong> 吗!通过这些类型,我们可以上传Json串,图片等内容真是方便又好用啊。</p>    <h2>总结</h2>    <p>经过上面的介绍我相信大家对OkHttp简单使用有了一定的了解,OkHttp3使用起来是不是很简单呢,但是每一次请求的步骤都有着大量重复的地方,这要是在实际开发中,还不把人累着啊,本着节约开(tou)发周(lan)期的目的,咳咳,后面的文章会进一步的带领大家学习OkHttp3的高级用法和OkHttp工具类的封装哦,敬请期待。</p>    <p>参考:</p>    <ol>     <li><a href="/misc/goto?guid=4958964956476581901" rel="nofollow,noindex">https://github.com/square/okhttp</a></li>     <li><a href="/misc/goto?guid=4958966067602601107" rel="nofollow,noindex">Android OkHttp完全解析 是时候来了解OkHttp了</a></li>    </ol>    <p> </p>    <p>来自:http://www.jianshu.com/p/7d88613c0b0f</p>    <p> </p>