你想要的系列:网络请求框架OkHttp3全解系列 - (一)OkHttp的基本使用

Okhttp系列文章:
你想要的系列:网络请求框架OkHttp3全解系列 - (一)OkHttp的基本使用
你想要的系列:网络请求框架OkHttp3全解系列 - (二)OkHttp的工作流程分析
你想要的系列:网络请求框架OkHttp3全解系列 - (三)拦截器详解1:重试重定向、桥、缓存(重点)
你想要的系列:网络请求框架OkHttp3全解系列 - (四)拦截器详解2:连接、请求服务(重点)

因为一直没有去详细了解okhttp原理,在网上找了很多文章,发现没有类似 郭霖的Glide系列那种 细致的详解系列,很不爽,决定自己整一下,应该会耗费不少时间,不过也是对自己的挑战,还有点兴奋呢。也希望和大家一起讨论。
预计okhttp系列有4篇,使用方法、流程分析、缓存和连接池、使用扩展及封装。
这是第一篇,按照惯例,就介绍基本的使用方法,比较简单。
好了,闲话少叙,开始!

所需 预备知识:
HTTP协议详解
HTTP请求报文和响应报文

现在Android中的网络请求框架,基本都是okhttp和Retrofit一统天下,而Retrofit又是以okhttp为基础,所以系统学习okhttp的使用和原理就很有必要了。

okhttp是由square公司开发,Android中公认最好用的网络请求框架,在接口封装上做的简单易用,GitHub地址。

它有以下默认特性:

  • 支持HTTP/2,允许所有同一个主机地址的请求共享同一个socket连接
  • 使用连接池减少请求延时
  • 透明的GZIP压缩减少响应数据的大小
  • 缓存响应内容,避免一些完全重复的请求

当网络出现问题的时候OkHttp 会自动恢复一般的连接问题,如果你的服务有多个IP地址,当第一个IP请求失败时,OkHttp会交替尝试你配置的其他IP。

一、引入

gradle引入依赖即可。

    implementation 'com.squareup.okhttp3:okhttp:3.14.7'
    implementation 'com.squareup.okio:okio:1.17.5'

3.14.x版本及以前的版本,采用Java语言编写,4.0.0以后采用kotlin语言;本系列文章中源码引自3.14.x版本,以Java语言讲解。

其中Okio库 是对Java.io和java.nio的补充,以便能够更加方便,快速的访问、存储和处理你的数据。OkHttp的底层使用该库作为支持。

另外,别忘了申请网络请求权限,如果还使用网络请求的缓存功能,那么还要申请读写外存的权限:

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

二、使用方式

基本使用步骤如下

  • 构建客户端对象OkHttpClient
  • 构建请求Request
  • 生成Call对象
  • Call发起请求(同步/异步)

下面跟着具体使用实例,详细介绍。

2.1 get请求

以百度主页为例,进行Get请求:

        OkHttpClient httpClient = new OkHttpClient();

        String url = "https://www.baidu.com/";
        Request getRequest = new Request.Builder()
                .url(url)
                .get()
                .build();

        Call call = httpClient.newCall(getRequest);

        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    //同步请求,要放到子线程执行
                    Response response = call.execute();
                    Log.i(TAG, "okHttpGet run: response:"+ response.body().string());
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }).start();

首先,创建了OkHttpClient实例,接着用Request.Builder构建了Request实例并传入了百度主页的url,然后httpClient.newCall方法传入Request实例生成call,最后在子线程调用call.execute()执行请求获得结果response。

所以,使用OkHttp进行get请求,是比较简单的,只要在构建Request实例时更换url就可以了。

异步请求

有个问题,你可能注意到了,这里是放在子线程执行请求的,这是因为call.execute()是同步方法。想要在主线程直接使用而不用手动创建子线程可以嘛?当然可以,使用call.enqueue(callback)即可:

        call.enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                Log.i(TAG, "okHttpGet enqueue: onResponse:"+ response.body().string());

                ResponseBody body = response.body();
                String string = body.string();
                byte[] bytes = body.bytes();
                InputStream inputStream = body.byteStream();
            }
        });

call.enqueue会异步执行,需要注意的是,两个回调方法onFailure、onResponse是执行在子线程的,所以如果想要执行UI操作,需要使用Handler切换到UI线程。

取消请求

每一个Call只能执行一次(原因会在下篇流程分析中说明)。 如果想要取消正在执行的请求,可以使用call.cancel(),通常在离开页面时都要取消执行的请求的。

结果处理

请求回调的两个方法是指 传输层 的失败和成功。onFailure通常是connection连接失败或读写超时;onResponse是指,成功的从服务器获取到了结果,但是这个结果的响应码可能是404、500等,也可能就是200(response.code()的取值)。

如果response.code()是200,表示应用层请求成功了。此时我们可以获取Response的ResponseBody,这是响应体。从面看到,可以从ResponseBody获取string、byte[]、InputStream,这样就可以对结果进行很多操作了,比如UI上展示string(要用Handler切换到UI线程)、通过InputStream写入文件等等。

上面异步请求执行后 结果打印如下:

2020-05-04 21:52:56.446 32681-3631/com.hfy.androidlearning I/OkHttpTestActivity: okHttpGet run: response:<!DOCTYPE html>
    <!--STATUS OK--><html> <head><meta http-equiv=content-type content=text/html;charset=utf-8><meta http-equiv=X-UA-Compatible content=IE=Edge><meta content=always name=referrer><link rel=stylesheet type=text/css href=https://ss1.bdstatic.com/5eN1bjq8AAUYm2zgoY3K/r/www/cache/bdorz/baidu.min.css><title>百度一下,你就知道</title></head> <body link=#0000cc> <div id=wrapper> <div id=head> <div class=head_wrapper> <div class=s_form> <div class=s_form_wrapper> <div id=lg> <img hidefocus=true src=//www.baidu.com/img/bd_logo1.png width=270 height=129> 
新闻 hao123 地图 视频 贴吧

你可能感兴趣的:(android,okhttp,进阶)