Okhttp

Prerequisites:

同步 非同步 get post

類型 特點 使用方法
同步 (Synchronous) 會阻塞目前執行緒,直到伺服器回應 call.execute()
非同步 (Asynchronous) 不阻塞執行緒,回應會在callback 回呼中收到 call.enqueue(callback)

所謂的阻塞(Blocking),就是要等待網路連線回應,才進行下一個程式碼執行。

非同步,就是不用等待網路連線,可以先執行其它程式碼,不用卡在那邊等待網路回應。

同步 get

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import okhttp3.OkHttpClient
import org.junit.Test

import okhttp3.Request
class OkhttpTest {
  val client = OkHttpClient()
  @Test
  fun sync_get() {
    val request = Request.Builder()
      .url("https://www.httpbin.org/get")
      .get()
      .build()
    val call = client.newCall(request)
    val response = call.execute()
    if (response.isSuccessful) {
      response.body().let { body ->
        println("body = ${body?.string()}")
      }
    }
  }
}

非同步 get

Kotlin 避免回調地獄,改用協程取代call.enqueue()。
我在這邊使用withContext,也可以用launch + withContext,達到非同步。

另外注意!body?.string()只能呼叫一次,不能呼叫2次,要使用一個變數,把它存起來,呼叫2次會出現以下的錯誤,因為讀取第一次時資源就關閉了,讀第2次,就會有closed的Exception,因為資源已關閉。

java.lang.IllegalStateException: closed
1
val bodyString = body?.string()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
suspend fun async_get() = withContext(Dispatchers.IO) {
  val request = Request.Builder()
    .url("https://www.httpbin.org/get")
    .get()
    .build()

  client.newCall(request).execute().use { response ->
    if (response.isSuccessful) {
      response.body().let { body ->
        val bodyString = body?.string()
        println("body = $bodyString")
        bodyString
      }
    } else {
      null
    }
  }
}

@Test
fun test1() = runBlocking {
  async_get()
  println()
}

results matching ""

    No results matching ""