iT邦幫忙

2023 iThome 鐵人賽

DAY 5
0

OKHttp

什麼是 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

暫時先做簡單的 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>

d5_1.png

畫面處理完畢,現在來處理 API~

使用 OKHttp

前置作業

  1. Gradle 引用

    在 App 層級的 gradle 引用 OKHttp 套件 :

    implementation "com.squareup.okhttp3:okhttp:4.10.0"
    
  2. 因為是網路連線,我們得要在 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()
            }

執行一下,結果報錯了,因為筆者想給大家看如果沒有打開網路權限會出現的錯誤訊息,這樣下次看到就能回想起來~

d5_2.png

再執行一次,這時又出現另一個錯誤訊息 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

d5_3.png

再執行一次,就可以看到撈回來的資料了。

畫面的文字亂的很噁心,沒事,今天只是測試,後續會在學習簡單的使用 RecyclerView 呈現資料。

d5_4.png

今天學習了同步執行,明天來試試看非同步執行呼叫 API,會使用到 Coroutines 來處理非同步事件。

今日份碎念

筆者也是邊學邊消化,真的花費相當多的時間,明天的 Coroutines 是沒有碰過的新東西,再來看看會遇到什麼問題,看到這邊的大家都是我的學伴呀 ! 真的超累的,一起努力~~~

今日推推 ❤️❤️❤️
Yes


上一篇
Day4 使用 OKHttp 串接全台咖啡廳資料的 API -1
下一篇
Day6 使用 OKHttp 串接全台咖啡廳資料的 API - 3 | 非同步執行 - Callback
系列文
喝咖啡要30天?一起用 Kotlin 打造尋找好喝咖啡的 App30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言