基本上现在面试都会问网络框架相关问题,例如目前比较流行的okhttp3以及retrofit,我们先来说一下okhttp
先在gradle中导入okhttp的依赖库:
implementation 'com.squareup.okhttp3:okhttp:3.14.2'
implementation 'com.squareup.okio:okio:1.17.4'
接下来在Manifest中添加网络权限
<uses-permission android:name="android.permission.INTERNET" />
基本使用
1.GET同步请求
//GET同步请求
public void get(){
//先创建okhttpClient对象
OkHttpClient client=new OkHttpClient();
//创建request对象,默认为get请求
Request request=new Request.Builder().get().url("http://www.jianshu.com/u/9df45b87cfdf").build();
//将request传入call对象中
Call call=client.newCall(request);
try {
//调用同步方法
Response response=call.execute();
//得到返回结果
String str=response.body().string();
} catch (IOException e) {
e.printStackTrace();
}
}
2.GET异步请求
//GET异步请求
public void get(){
OkHttpClient okHttpClient=new OkHttpClient();
Request request=new Request.Builder()
.get()
.url("http://www.jianshu.com/u/9df45b87cfdf")
.build();
Call call=okHttpClient.newCall(request);
call.enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
//请求失败返回
}
@Override
public void onResponse(Call call, Response response) throws IOException {
//请求成功返回
}
});
}
3.POST异步请求(同步请求类似,在这里就不写代码了)
public void postParameter(){
OkHttpClient client=new OkHttpClient();
FormBody formBody=new FormBody.Builder()
.add("username","123")
.add("password","123")
.build();
Request request=new Request.Builder()
.url("http://www.jianshu.com/")
.post(formBody)
.build();
Call call=client.newCall(request);
call.enqueue(new Callback(){
@Override
public void onFailure(Call call, IOException e) {
//请求失败
}
@Override
public void onResponse(Call call, Response response) throws IOException {
//获得请求成功的内容
String responseStr=response.body().string();
}
});
}
更多实现方式可以看一看刘望舒的博客:https://blog.csdn.net/itachi85/article/details/51190687。
我们在这里总结一下基本的使用流程:先创建OkHttpClient对象,再去创建Request(如果是post请求则创RequestBody),接下来通过我们创建的okhttpClient对象的newCall方法赋值给Call对象,最后call再去调用exectue或者enqueue获得请求结果。
源码分析
1.OkHttpClient的创建
//默认调用此构造函数
public OkHttpClient() {
this(new Builder());
}
//最终调用该构造函数
OkHttpClient(Builder builder) {
this.dispatcher = builder.dispatcher;
this.proxy = builder.proxy;
this.protocols = builder.protocols;
this.connectionSpecs = builder.connectionSpecs;
this.interceptors = Util.immutableList(builder.interceptors);
this.networkInterceptors = Util.immutableList(builder.networkInterceptors);
this.eventListenerFactory = builder.eventListenerFactory;
this.proxySelector = builder.proxySelector;
this.cookieJar = builder.cookieJar;
this.cache = builder.cache;
this.internalCache = builder.internalCache;
this.socketFactory = builder.socketFactory;
boolean isTLS = false;
for (ConnectionSpec spec : connectionSpecs) {
isTLS = isTLS || spec.isTls();
}
我们发现这些参数都是builder中的参数,我们看看builder中干了什么
public Builder() {
//任务调度器,控制并发请求,异步的时候通过它来调度所有网络请求
dispatcher = new Dispatcher();
//协议,里面有HTTP2和HTTP_1_1
protocols = DEFAULT_PROTOCOLS;
//默认连接配置
connectionSpecs = DEFAULT_CONNECTION_SPECS;
//事件监听器
eventListenerFactory = EventListener.factory(EventListener.NONE);
//代理选择器
proxySelector = ProxySelector.getDefault();
if (proxySelector == null) {
proxySelector = new NullProxySelector();
}
//http cookie持久化策略
cookieJar = CookieJar.NO_COOKIES;
//socket工厂
socketFactory = SocketFactory.getDefault();
//主机名验证
hostnameVerifier = OkHostnameVerifier.INSTANCE;
//约束信任证书
certificatePinner = CertificatePinner.DEFAULT;
//代理认证
proxyAuthenticator = Authenticator.NONE;
//认证者
authenticator = Authenticator.NONE;
//连接池
connectionPool = new ConnectionPool();
//DNS解析
dns = Dns.SYSTEM;
//SSL重定向
followSslRedirects = true;
//重定向
followRedirects = true;
//是否失败自动重连
retryOnConnectionFailure = true;
//完整请求调用时间
callTimeout = 0;
//连接超时
connectTimeout = 10_000;
//读取超时
readTimeout = 10_000;
//发送数据超时
writeTimeout = 10_000;
//时间间隔
pingInterval = 0;
}
Builder(OkHttpClient okHttpClient) {
this.dispatcher = okHttpClient.dispatcher;
...
}
okhttpClient通过建造者模式,在类实例化的时候调用builder将相关参数设为默认值。如果我们创建OkhttpClient通过Builder方式,我们还可以使用Builder中的一些其他的API
OkHttpClient.Builder builder=new OkHttpClient.Builder()
.addInterceptor()
.cache()
.callTimeout()
.connectionPool()
//等等很多API
.build();
至此OkHttpClient就创建完毕,主要就是进行赋值,将okhttpClient的默认参数配置好
需要注意:
OkHttpClient(Builder builder) {
boolean isTLS = false;
for (ConnectionSpec spec : connectionSpecs) {
isTLS = isTLS || spec.isTls();
}
if (builder.sslSocketFactory != null