大纲
首先,发送请求,我们先要创建请求报文Request,通过Request,newCall的方法,创建好我们实际的Http请求Call,而Call呢,本身是一个接口,所以说他的实现在它的具体实现类RealCall中。这时候,我们需要判断,他多调用的是Call的execute()方法,还是enqueue()方法,来判断是同步还是异步请求的区别。
异步是需要Request,然后创建Call,Call也是通过实际的RealCall来进行相应的操作,同步和异步,最大的区别就是异步它会开启一个线程,是AsyncCall,AsyncCall其实就是一个Runnable。
Dispatcher类其实是okhttp的分发器类,这个分发器来决定这个异步请求是执行还是就绪的选择。
不管是同步还是异步,它最后都会进入getResponseWithInterceptorChain()方法,这个方法的内部,其实构建了一个拦截器的链,然后通过依次执行这个拦截器中的每一个不同作用的拦截器来获取服务器的数据返回。
okhttp同步请求
请求步骤
1. 创建一个OkHttpClient类。代表着OKHttp请求的一个客户端类,在整个okhttp库中,这个OkHttpClient类是处于一个很核心的地位。很多功能需要通过这个客户端类进行转发,或者直接由这个客户端类进行实现。
它的创建方式有两种:
一、通过默认的,也就是直接通过new一个对象来实例OkHttpClient。
二、考虑到现实网络情况下是比较复杂的,这时候需要来设置一些参数。用到了OkHttpClient中的一个静态内部类Builder,在这个静态内部类中,有一个构造方法:
public Builder() {
dispatcher = new Dispatcher();
protocols = DEFAULT_PROTOCOLS;
connectionSpecs = DEFAULT_CONNECTION_SPECS;
eventListenerFactory = EventListener.factory(EventListener.NONE);
proxySelector = ProxySelector.getDefault();
if (proxySelector == null) {
proxySelector = new NullProxySelector();
}
cookieJar = CookieJar.NO_COOKIES;
socketFactory = SocketFactory.getDefault();
hostnameVerifier = OkHostnameVerifier.INSTANCE;
certificatePinner = CertificatePinner.DEFAULT;
proxyAuthenticator = Authenticator.NONE;
authenticator = Authenticator.NONE;
connectionPool = new ConnectionPool();
dns = Dns.SYSTEM;
followSslRedirects = true;
followRedirects = true;
retryOnConnectionFailure = true;
callTimeout = 0;
connectTimeout = 10_000;
readTimeout = 10_000;
writeTimeout = 10_000;
pingInterval = 0;
}
在这其中,有一个行是这样的:
dispatcher = new Dispatcher();
这个Dispatcher类是分发器类,是OkHttp核心之一。
Dispatcher类会接到同步或者异步的请求队列,然后根据它所要条件来进行相应的同步或异步请求的分发。
当通过使用Builder的模式设置好参数后,就可以调用OkHttpClient.build()方法来完成整个的OkHttpClient对象创建。
OkHttpClient client = new OkHttpClient.Builder().readTimeout(5,TimeUnit.SECOUNDS).build();
这其中只是将超时时间设置为了5秒,这就完成了第一步OkHttpClient的创建。
2. 创建Request。
Request其实就是请求报文的一些信息。我们发送一个OkHttp请求,肯定会有一个Request、Response等。这里面,包括我们的一些常用的请求url的地址,请求的方法(get/post)等,还有他可以设置请求头,比如说cookie。
一般,这个Request也是通过上面的Builder模式来进行创建的。
Request request = new Request.Builder().url("http://www.baidu.com").get().build();
这里,我们通过Builder模式,设置了请求的url,随便写的百度地址,然后调用了build()方法,来完成了整个Request请求报文的创建。
3. 创建Call对象。
什么是Call对象?Call对象其实是代表着一个实际的Http请求,可以将Call理解成为Request和Reponse之间的一个桥梁。
Call call = client.newCall(request);
通过newCall这个方法,并把刚才所创建好的request当作参数传入进去,创建好我们的Call对象,这是第三步。
同步请求和一部请求在他们的前三步都是一样的,但是,第四步通过call来进行同步和异步的调用,就开始不一样了。
4. Call的execute()方法进行相应报文读取。
try{
Response response = call.execute();
System.out.println(response.body().string());
}catch(IOException e){
e.printStackTrace();
}
这个Response就是响应报文的信息,比如响应报文、响应头等。
同步请求和异步请求最大的区别就在于同步调用的execute()这个方法。在这个方法的最后,我们打印了response的body体。
同步方法注意
OkHttp同步发送请求后,就会进入阻塞状态,直至收到响应。这一点也是OkHttp同步和异步请求最大的不同点,因为异步请求是不会阻塞当前线程的,它的做法是起一个工作线程,也就是一个子线程,去进行数据的处理。
异步请求方法
异步步骤
1. 首先,前两步与同步请求一样,他先会创建一个OkHttpClient和Request对象,两者都是使用Builder模式来进行创建的,它可以设置一些它所需要的一些参数,都是通过.build()方法来完成构建工作。然后调用client的newCall方法来传入request的对象,来进行Call对象的创建。这时候,Call对象已经代表准备执行的网络请求了。
2. 如果想要执行异步请求的话,就需要与同步请求有所区别了。想使用异步请求,它所调用的是enqueue方法,在方法的内部,它会做一个Callback的对象。这里需要注意,当异步请求调用enqueue方法的时候,他是会去开启一个新的工作线程的,然后okhttp会让实际的网络请求在这个工作线程中执行,也就是这个子线程中执行。
call.enqueue(new Callback(){
@Override
public void onFailure(Call call,IOException e){
system.out.println("Faile");
}
@Override
public void onResponse(Call call,Response response)throws IOException{
system.out.println("response.body().String()");
}
});
当异步请求执行成功之后,它会回调Callback对象当中的onResponse这个方法,在这个onResponse这个方法里,它可以对返回的成功的数据进行处理。
当异步请求执行失败,或者调用了cancel方法之后,他就会回调我们callback对象的onFailure方法。
异步方法注意
onResponse和onFailure两个方法都是在工作线程,也就是在子线程中处理的。
同步方法与异步方法的区别
1. 发起请求的方法调用
同步调用execute()方法;异步调用enqueue()方法,然后传入一个Callback对象。
2. 线程阻塞与否
同步是阻塞当前线程的;异步是不会阻塞当前线程的,相反,它会开启一个工作线程来完成网络请求的工作。