1.OkHttp用法
(1).Get请求 new OkHttpClient ,构造Request对象,调用newCall方法获取Call对象,通过call#enqueue或者excute来提交请求。
String url = "http://wwww.baidu.com";
OkHttpClient okHttpClient = new OkHttpClient();
//POST提交表单
FormBody formBody = new FormBody.Builder()
.add("username", "your_username")
.add("password", "your_password")
.build();
Request request1=new Request.Builder().url("url").post(formBody).build();
//POST提交JSON
MediaType mediaType = MediaType.get("application/json; charset=utf-8");
String jsonBody = "{\"key\":\"value\"}";
RequestBody body = RequestBody.create(mediaType,jsonBody);
Request request2=new Request.Builder().url("").post(body).build();
Call call = okHttpClient.newCall(request1);
call.enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
Log.d(TAG, "onFailure: ");
}
@Override
public void onResponse(Call call, Response response) throws IOException {
Log.d(TAG, "onResponse: " + response.body().string());
}
});
(2).Post请求 在构建Request对象的时候,需要多构造一个RequestBody对象,同时指定MediaType用于描述请求/响应body的内容类型 Post提交String
MediaType mediaType = MediaType.parse("text/x-markdown; charset=utf-8");
String requestBody = "I am Jdqm.";
Request request = new Request.Builder()
.url("https://api.github.com/markdown/raw")
.post(RequestBody.create(mediaType, requestBody))
.build();
OkHttpClient okHttpClient = new OkHttpClient();
okHttpClient.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
Log.d(TAG, "onFailure: " + e.getMessage());
}
@Override
public void onResponse(Call call, Response response) throws IOException {
Log.d(TAG, response.protocol() + " " +response.code() + " " + response.message());
Headers headers = response.headers();
for (int i = 0; i < headers.size(); i++) {
Log.d(TAG, headers.name(i) + ":" + headers.value(i));
}
Log.d(TAG, "onResponse: " + response.body().string());
}
});
Post提交流
RequestBody requestBody = new RequestBody() {
@Nullable
@Override
public MediaType contentType() {
return MediaType.parse("text/x-markdown; charset=utf-8");
}
@Override
public void writeTo(BufferedSink sink) throws IOException {
sink.writeUtf8("I am Jdqm.");
}
};
Request request = new Request.Builder()
.url("https://api.github.com/markdown/raw")
.post(requestBody)
.build();
OkHttpClient okHttpClient = new OkHttpClient();
okHttpClient.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
Log.d(TAG, "onFailure: " + e.getMessage());
}
@Override
public void onResponse(Call call, Response response) throws IOException {
Log.d(TAG, response.protocol() + " " +response.code() + " " + response.message());
Headers headers = response.headers();
for (int i = 0; i < headers.size(); i++) {
Log.d(TAG, headers.name(i) + ":" + headers.value(i));
}
Log.d(TAG, "onResponse: " + response.body().string());
}
});
Post提交文件
MediaType mediaType = MediaType.parse("text/x-markdown; charset=utf-8");
OkHttpClient okHttpClient = new OkHttpClient();
File file = new File("test.md");
Request request = new Request.Builder()
.url("https://api.github.com/markdown/raw")
.post(RequestBody.create(mediaType, file))
.build();
okHttpClient.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
Log.d(TAG, "onFailure: " + e.getMessage());
}
@Override
public void onResponse(Call call, Response response) throws IOException {
Log.d(TAG, response.protocol() + " " +response.code() + " " + response.message());
Headers headers = response.headers();
for (int i = 0; i < headers.size(); i++) {
Log.d(TAG, headers.name(i) + ":" + headers.value(i));
}
Log.d(TAG, "onResponse: " + response.body().string());
}
});
Post提交表单
HttpClient okHttpClient = new OkHttpClient();
RequestBody requestBody = new FormBody.Builder()
.add("search", "Jurassic Park")
.build();
Request request = new Request.Builder()
.url("https://en.wikipedia.org/w/index.php")
.post(requestBody)
.build();
okHttpClient.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
Log.d(TAG, "onFailure: " + e.getMessage());
}
@Override
public void onResponse(Call call, Response response) throws IOException {
Log.d(TAG, response.protocol() + " " +response.code() + " " + response.message());
Headers headers = response.headers();
for (int i = 0; i < headers.size(); i++) {
Log.d(TAG, headers.name(i) + ":" + headers.value(i));
}
Log.d(TAG, "onResponse: " + response.body().string());
}
});
Post提交分块请求
private static final String IMGUR_CLIENT_ID = "...";
private static final MediaType MEDIA_TYPE_PNG = MediaType.parse("image/png");
private void postMultipartBody() {
OkHttpClient client = new OkHttpClient();
// Use the imgur image upload API as documented at https://api.imgur.com/endpoints/image
MultipartBody body = new MultipartBody.Builder("AaB03x")
.setType(MultipartBody.FORM)
.addPart(
Headers.of("Content-Disposition", "form-data; name=\"title\""),
RequestBody.create(null, "Square Logo"))
.addPart(
Headers.of("Content-Disposition", "form-data; name=\"image\""),
RequestBody.create(MEDIA_TYPE_PNG, new File("website/static/logo-square.png")))
.build();
Request request = new Request.Builder()
.header("Authorization", "Client-ID " + IMGUR_CLIENT_ID)
.url("https://api.imgur.com/3/image")
.post(body)
.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 {
System.out.println(response.body().string());
}
});
}
2.OkHttp原理
(2.1).初步流程图
(2.2). OkHttp.newCall()流程分析
//基本使用
OkHttpClient okHttpClient=new OkHttpClient().newBuilder().build();
Request request=new Request.Builder().build();
Call realCall= okHttpClient.newCall(request);
realCall.enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
}
@Override
public void onResponse(Call call, Response response) throws IOException {
}
});
static RealCall newRealCall(OkHttpClient client, Request originalRequest, boolean forWebSocket) {
// Safely publish the Call instance to the EventListener.
RealCall call = new RealCall(client, originalRequest, forWebSocket); //实例化一个RealCall对象
call.eventListener = client.eventListenerFactory().create(call);
return call;
}
//RealCall构造函数
private RealCall(OkHttpClient client, Request originalRequest, boolean forWebSocket) {
this.client = client;
this.originalRequest = originalRequest; //初始化Request
this.forWebSocket = forWebSocket;
//初始化重试(重定向)拦截器
this.retryAndFollowUpInterceptor = new RetryAndFollowUpInterceptor(client, forWebSocket);
}
2.3.enqueue流程分析
//RealCall中
public void enqueue(Callback responseCallback) {
//调用Dispatcher把AsyncCall加入队列
client.dispatcher().enqueue(new AsyncCall(responseCallback));
}
//Dispatcher中
synchronized void enqueue(AsyncCall call) {
//如果请求数小于64且同一域名请求小于5个,就把AsyncCall加入runningAsyncCalls队列,然后启动线程池执行,否则就把AsyncCall放入readAsyncCalls队列。
if (runningAsyncCalls.size() < maxRequests && runningCallsForHost(call) < maxRequestsPerHost) {
runningAsyncCalls.add(call);
executorService().execute(call);
} else {
readyAsyncCalls.add(call);
}
}
//线程池创建
public synchronized ExecutorService executorService() {
if (executorService == null) {
executorService = new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>(), Util.threadFactory("OkHttp Dispatcher", false));
}
return executorService;
}
2.4.AsyncCall
final class AsyncCall extends NamedRunnable {
private final Callback responseCallback;
AsyncCall(Callback responseCallback) {
super("OkHttp %s", redactedUrl());
this.responseCallback = responseCallback;
}
protected void execute() {
boolean signalledCallback = false;
try {
Response response = getResponseWithInterceptorChain();
if (retryAndFollowUpInterceptor.isCanceled()) {
signalledCallback = true;
responseCallback.onFailure(RealCall.this, new IOException("Canceled"));
} else {
signalledCallback = true;
responseCallback.onResponse(RealCall.this, response);
}
} catch (IOException e) {
if (signalledCallback) {
Platform.get().log(INFO, "Callback failure for " + toLoggableString(), e);
} else {
eventListener.callFailed(RealCall.this, e);
responseCallback.onFailure(RealCall.this, e);
}
} finally {
client.dispatcher().finished(this);
}
}
}
//把请求队列从runningAsyncCalls中移除,
void finished(AsyncCall call) {
finished(runningAsyncCalls, call, true);
}
private <T> void finished(Deque<T> calls, T call, boolean promoteCalls) {
int runningCallsCount;
Runnable idleCallback;
synchronized (this) {
//把AsyncCall从runningAsyncCalsl中移除
if (!calls.remove(call)) throw new AssertionError("Call wasn't in-flight!");
if (promoteCalls) promoteCalls();
runningCallsCount = runningCallsCount();
idleCallback = this.idleCallback;
}
if (runningCallsCount == 0 && idleCallback != null) {
idleCallback.run();
}
}
//然后遍历readyAsyncCalls队列,取出AysncCall加入到runningAsyncs队列,启动线程池立即执行。
private void promoteCalls() {
if (runningAsyncCalls.size() >= maxRequests) return; // Already running max capacity.
if (readyAsyncCalls.isEmpty()) return; // No ready calls to promote.
for (Iterator<AsyncCall> i = readyAsyncCalls.iterator(); i.hasNext(); ) {
AsyncCall call = i.next();
if (runningCallsForHost(call) < maxRequestsPerHost) {
i.remove();
runningAsyncCalls.add(call);
executorService().execute(call);
}
if (runningAsyncCalls.size() >= maxRequests) return; // Reached max capacity.
}
}
2.5.getResponseWithInterceptorChain()流程分析
Response getResponseWithInterceptorChain() throws IOException {
// Build a full stack of interceptors.
List<Interceptor> interceptors = new ArrayList<>();
interceptors.addAll(client.interceptors());//自定义拦截器
/* 重试拦截器,判断用户是否取消了请求,在获得结果之后,会根据响应码判断是否需要重定向*/
interceptors.add(retryAndFollowUpInterceptor);
/* 桥接拦截器,负责在http协议中加入必备字段如:host:192.168..0.1:8080,accept encodeing:gzip,connection:keep alive ,在获得结果之后,调用保存cookie接口并解析Gzip数据.*/
interceptors.add(new BridgeInterceptor(client.cookieJar()));
/*发起http请求的时候,会尝试读取缓存的响应数据,如果缓存存在有效数据,并满足缓存策略,则直接
返回缓存的数据,避免再次进行网络请求,如果不存在,会生成一个缓存策略,根据缓存策略指示,是否需要网络请求 */
interceptors.add(new CacheInterceptor(client.internalCache()));
/*负责建立一个新的tcp/ip连接,并获得对应的socket流*/
interceptors.add(new ConnectInterceptor(client));
if (!forWebSocket) {
interceptors.addAll(client.networkInterceptors());
}
/*利用得到的socket.getOutputStream 向服务器发送Http请求,解析读取的响应数据,并将数据封装成response对象返回.*/
interceptors.add(new CallServerInterceptor(forWebSocket));
Interceptor.Chain chain = new RealInterceptorChain(interceptors, null, null, null, 0,
originalRequest, this, eventListener, client.connectTimeoutMillis(),
client.readTimeoutMillis(), client.writeTimeoutMillis());
return chain.proceed(originalRequest);
}
2.6.Interceptor接口
public interface Interceptor {
Response intercept(Chain chain) ;
interface Chain {
Request request();
Response proceed(Request request) ;
}
2.7.RealInterceptors实现类
public final class RealInterceptorChain implements Interceptor.Chain {
public RealInterceptorChain(List<Interceptor> interceptors, int index, Request request){
this.interceptors = interceptors;
this.index = index;
this.request = request;
}
public Response proceed(Request request){
//index+1,可以在RealInterceptorChain中调用下一个Interceptor
RealInterceptorChain next = new RealInterceptorChain(interceptors, index + 1, request);
Interceptor interceptor = interceptors.get(index);//得到当前责任人
Response response = interceptor.intercept(next);
return response;
}
}