28 Okhttp原始碼分析&實踐(六)【實踐環節:Okhttp的基本框架搭建&請求實現】
開啟掘金成長之旅!這是我參與「掘金日新計劃 · 12 月更文挑戰」的第28天,點選檢視活動詳情
http的基礎知識、okhttp的框架基本原始碼,我們通過之前課程都已學習總結過,接下來,就是關鍵的實踐課程。 各位coder,需要緊跟小編腳步,要開始加速飆車了。
1.基本框架的搭建實現
既然不知道如何入手,我們不妨就以okhttp的基本使用程式碼為例,作為入手點,去開始程式設計實現。新建一個工程,小編這裡就以OkhttpStudy來命名。裡面基本啥也沒有引用。
```java plugins { id 'com.android.application' }
android { compileSdk 32
defaultConfig {
applicationId "com.itbird.okhttpstudy"
minSdk 22
targetSdk 32
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
}
dependencies {
implementation 'androidx.appcompat:appcompat:1.3.0'
implementation 'com.google.android.material:material:1.4.0'
implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.3'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
} ```
1.1 搭建框架
我們在MainActivity中,直接將使用程式碼copy過來。 ```java //第一步:new okhttpclient OkhttpClient okhttpClient = new OkhttpClient.Builder().build();
//第二步:new Requset
Request request = new Request.Builder().url("http://www.baidu.com").method(Method.GET).build();
//第三步:new Call
Call call = okhttpClient.newCall(request);
//第四部:執行
call.enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
Log.d(Constants.TAG, "MainActivity onFailure");
}
@Override
public void onResponse(Call call, Response response) throws IOException {
Log.d(Constants.TAG, "MainActivity onResponse" + response.toString());
}
});
```
有人會說,小編你這不是又在騙人嗎?你gradle中都沒有引入okhttp,這裡自己MainActivity中這樣寫,不就都報錯了嗎?小編只想說
我們通過AS的提示功能, 一一開始新建這些類、這些方法,OkhttpClient、OkhttpClient.Builder()、build()方法等,這樣更加快捷一些,也許新建過程中,您會說,這不就是一些空方法嗎?對的,就是空方法,我們接下來就是填充這些空方法,用自己已有的知識,去試著實現它。
大家在這個過程中,謹記一條,我們最初的本心目的,並不是想要去實現一個okhttp,我們僅僅是通過這樣的學習手段,想要將自己已有的知識和okhttp核心實現,去在腦中關聯起來。
1.2 OkhttpClient類和方法建立
OkhttpClient,okhttpClient,是幹什麼的,那麼裡面肯定有一個執行器,其實說白了,就是執行緒池
```java package com.itbird.okhttpstudy;
/* * Created by itbird on 2022/11/21 / public class OkhttpClient { private Builder builder; private Dispatcher dispatcher;
public OkhttpClient(Builder builder) {
this.builder = builder;
dispatcher = builder.dispatcher;
}
public Call newCall(Request request) {
return new RealCall(request, this);
}
public static class Builder {
private Dispatcher dispatcher;
public Builder() {
dispatcher = new Dispatcher();
}
public OkhttpClient build() {
return new OkhttpClient(this);
}
}
}
```
1.3 Request類和方法建立
開始逐層實現,requset是幹什麼的,當然是填充引數的、url、params、method,所以接下來,第二步,Request類和方法的建立
```java package com.itbird.okhttpstudy;
import java.util.HashMap; import java.util.Map;
/* * 請求 * Created by itbird on 2022/11/21 / public class Request { private Builder builder;
public Request(Builder builder) {
this.builder = builder;
}
public static class Builder {
private String url;
private Map<String, String> params;
private Method method;
public Builder() {
method = Method.GET;
params = new HashMap<>(20);
}
public Builder url(String url) {
this.url = url;
return this;
}
public Builder addParam(String key, String value) {
params.put(key, value);
return this;
}
public Request build() {
return new Request(this);
}
}
} ```
1.4 RealCall類和方法建立
到了這裡,執行緒池執行器有了,Requset也有了,是不是缺少runnable了,也就是執行緒了,那麼我們現在只有requset一個請求實體而已,那接下來要做的,就顯而易見了,就是把requset封裝為runnable任務,然後提交執行緒池執行
```java package com.itbird.okhttpstudy;
import android.util.Log;
import java.io.IOException;
/* * Created by itbird on 2022/11/21 / public class RealCall implements Call { private Request request; private OkhttpClient okhttpClient;
public RealCall(Request request, OkhttpClient okhttpClient) {
this.request = request;
this.okhttpClient = okhttpClient;
}
@Override
public void enqueue(Callback callback) {
okhttpClient.dispatcher.enqueue(new AsyncCall(callback));
}
@Override
public Response execute() {
return getResponseWithInterceptorChain();
}
private Response getResponseWithInterceptorChain() {
return null;
}
class AsyncCall extends NamedRunnable {
private Callback callback;
public AsyncCall(Callback callback) {
this.callback = callback;
}
public AsyncCall() {
}
@Override
public void execute() {
Log.d(Constants.TAG, "AsyncCall execute");
Response response = getResponseWithInterceptorChain();
if (callback != null) {
try {
callback.onResponse(RealCall.this, response);
} catch (IOException e) {
}
}
}
}
} ```
1.5 Dispatcher 類和方法建立
好了,到了這裡,任務也有了,缺少啥了?當然是缺少執行了,大家忘記了嗎?執行那裡還是空的呢
```java package com.itbird.okhttpstudy;
import java.util.concurrent.ExecutorService; import java.util.concurrent.SynchronousQueue; import java.util.concurrent.ThreadFactory; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit;
/* * 執行器 * Created by itbird on 2022/11/21 / public class Dispatcher { private ExecutorService executorService;
public void enqueue(RealCall.AsyncCall call) {
executorService().execute(call);
}
public synchronized ExecutorService executorService() {
if (executorService == null) {
executorService = new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>(), new ThreadFactory() {
@Override
public Thread newThread(Runnable runnable) {
Thread result = new Thread(runnable, "okhttp");
result.setDaemon(false);
return result;
}
});
}
return executorService;
}
}
```
到現在為止,程式碼可以正常運行了,我們看一下執行結果
本章到現在,大家其實從okhttp的使用入手,已經搭建實現了一個自己的okhttp框架,而且整體流程時可以跑通的,是否現在有個感覺?一切都並不是剛開始想的那麼困難了,是不?
所以也許一些事情,只要你去做了,才能真正知道難或者不難,而不是先給自己心理暗示,很難,導致問題或者需求的實現解決上,舉步維艱。
好了,接下來,就是去實現,真正的請求了,因為現在僅僅是流程跑通了而已。