什麼是 OKHttp 呢? 來看一下 ChatGPT 的回答 :
OKHttp(發音為"ok HTTP")是一個用於在Android和Java應用程序中執行HTTP請求的開源庫。它由 Square 公司開發,已經成為Android開發中非常流行的HTTP客戶端庫之一。OKHttp提供了簡單而強大的API,使開發人員能夠輕鬆地執行HTTP請求、處理響應和管理網絡連接。
白話文就是 OKHttp 是一個相當熱門的第三方套件,許多知名的套件像是 Volley 和 Retrofit 的底層也是基於此套件開發的。主要用於 Android 應用程式和 server 之間的 HTTP 溝通,我們可以簡單的透過 OKHttp 提供的 API,執行對 server 的 HTTP 請求。
這是 OKHttp 的官方文件,裡面也有簡單的範例,比如下方是丟給它一串 URL,然後取得它的回傳資料 :
OkHttpClient client = new OkHttpClient();
String run(String url) throws IOException {
Request request = new Request.Builder()
.url(url)
.build();
try (Response response = client.newCall(request).execute()) {
return response.body().string();
}
}
上面是說先實例化出 OkHttpClient,在將我們給他的參數 url 包給 request,最後呼叫 OkHttpClient 的 execute() 方法來做同步的連線 (Synchronous),這樣就可以取得回傳內容拉~~
上面是最基本的使用,很簡單吧! 我們的任務除了要透過 OKHttp 取得咖啡廳資料外,也要學會解析 JSON 字串,直接開始今日份的 Kotlin 吧~~
暫時先做簡單的 UI,確定可以吃到資料就好,畫面等之後在改 (還沒想好它要長什麼樣子),所以這邊就給一個 TextView 和 Button。
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="5dp"
tools:context=".MainActivity">
<TextView
android:id="@+id/tv_hello_kotlin"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!"
android:textSize="16sp"
app:layout_constraintBottom_toTopOf="@+id/button"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="GET"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
畫面處理完畢,現在來處理 API~
Gradle 引用
在 App 層級的 gradle 引用 OKHttp 套件 :
implementation "com.squareup.okhttp3:okhttp:4.10.0"
因為是網路連線,我們得要在 AndroidManifest.xml 內將網路權限打開 :
<uses-permission android:name="android.permission.INTERNET" />
其實現在不開也沒關係,這樣等等還可以欣賞一下報錯內容 ❤️❤️❤️
先遇到以後就會有印象拉~~
程式在執行時可分成兩種模式,同步 (Synchronous) 和非同步 (Asynchronous) 執行,兩者最大的差別在於程式是否會照順序執行。同步執行是由於程式在執行時會被阻塞,直到事件完成,也就是會按照程式碼的順序來做事,所以在閱讀上是相當直覺的;而在執行非同步任務時,程式碼是可以去做別的事情 (跳到其他地方),所以當任務結束時需要特別通知任務已完成。
這邊有更詳細的教學文,我們暫時先不多談,等後續談到非同步執行時在來細細品嘗。
先來做比較簡單的同步處理,因為程式會照著順序做,我們在閱讀時相對容易許多。
來透過同步處理撈出全台的咖啡廳資料,我們呼叫的 API : http://cafenomad.tw/api/v1.2/cafes/taipei
使用情境 : 點擊 GET 按鈕取得全台咖啡廳的資料,將撈到的資料顯示於 TextView 上。要記得在處理
以下為呼叫 API 的程式碼 :
// 創建一個單線程執行緒池
val service = Executors.newSingleThreadExecutor()
// 提交任務到執行緒池
service.submit {
// 創建一個 OkHttpClient 實例
val client = OkHttpClient()
// 設置要發送的 HTTP 請求
val request = Request.Builder()
.url("http://cafenomad.tw/api/v1.2/cafes/taipei")
.build()
// 在主線程中執行 OKHttp 請求(這是同步操作,會阻塞主線程)
try {
// 使用 OkHttpClient 發送同步請求
val response = client.newCall(request).execute()
// 檢查回應是否成功
if (response.isSuccessful) {
val responseBody = response.body?.string()
// 在主線程更新 UI,顯示回應內容
runOnUiThread {
binding.textView.text = responseBody
}
}
else {
// 處理請求失敗的情況
println("Request failed with code: ${response.code}")
}
// 關閉執行緒池
service.shutdown()
}
catch (e: Exception) {
e.printStackTrace()
}
執行一下,結果報錯了,因為筆者想給大家看如果沒有打開網路權限會出現的錯誤訊息,這樣下次看到就能回想起來~
再執行一次,這時又出現另一個錯誤訊息 java.net.UnknownServiceException: CLEARTEXT communication to cafenomad.tw not permitted by network security policy
這是使用到 http 就會遇到的問題,因為從 Android 9.0 開始 Http 就被禁止使用了。而我們的 TargetSdk 設定是33,該怎麼辦~~~~
網路是我的父母,問題丟上去後馬上就找到答案。這篇有詳細的回答與解法,筆者直接參考其中的方法 :
新增一個定義檔在 xml, network_security_config.xml
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
<base-config cleartextTrafficPermitted="true" />
</network-security-config>
剛剛設定網路權限的 AndroidManifest.xml 內也要加入以下程式碼來使用剛剛新增的自訂義檔案 :
<application … android:networkSecurityConfig="@xml/network_security_config" … />
完整的 AndroidManifest.xml
再執行一次,就可以看到撈回來的資料了。
畫面的文字亂的很噁心,沒事,今天只是測試,後續會在學習簡單的使用 RecyclerView 呈現資料。
今天學習了同步執行,明天來試試看非同步執行呼叫 API,會使用到 Coroutines 來處理非同步事件。
筆者也是邊學邊消化,真的花費相當多的時間,明天的 Coroutines 是沒有碰過的新東西,再來看看會遇到什麼問題,看到這邊的大家都是我的學伴呀 ! 真的超累的,一起努力~~~