withContext 切換執行緒
執行緒
- Dispatchers.IO
- Dispatchers.Default
- Dispatchers.Main
協程作用域
因為withContext是suspend 函式,所以要在協程作用域中,才能使用withContext()函式。
Junit的coroutine scope(協程作用域)是runBlocking,只有在runBlocking協程作用域下,就能呼叫suspend()函式。
1
2
3
4
5
6
7
8
  @Test
  fun coroutine13() = runBlocking {
  	// 切換至IO執行緒
    withContext(Dispatchers.IO) {
       // 程式碼
    }
    println(result2)
  }
使用方式1
withContext是suspend函式,要放在suspend函式中。
1
2
3
4
5
6
7
8
9
10
11
  suspend fun funName() {
    withContext(Dispatchers.IO) {
      delay(1000)
      println("test")
    }
  }
  @Test
  fun coroutine14() = runBlocking {
    funName()
  }
使用方式2
函式傳回值是withContext
1
2
3
4
5
6
7
8
9
  suspend fun funName() = withContext(Dispatchers.IO) {
      delay(1000)
      println("test")
  }
  @Test
  fun coroutine14() = runBlocking {
    funName()
  }
使用方式3
函式傳回值是協程作用域coroutineScope
1
2
3
4
5
6
7
8
9
10
11
  suspend fun funName() = coroutineScope {
    withContext(Dispatchers.IO) {
      delay(1000)
      println("test")
    }
  }
  @Test
  fun coroutine14() = runBlocking {
    funName()
  }
使用方式4
包在協程作用域中(coroutineScope、CoroutineScope、GlobalScope)。
1
2
3
4
5
6
7
8
9
  @Test
  fun coroutine14() = runBlocking {
    coroutineScope {
      withContext(Dispatchers.IO) {
        delay(1000)
        println("test")
      }
    }
  }
使用方式5
包在協程中(launch、async)。
1
2
3
4
5
6
7
8
9
10
  @Test
  fun coroutine14() = runBlocking {
    launch {
      withContext(Dispatchers.IO) {
        delay(1000)
        println("test")
      }
    }
    println()
  }
使用方式6
在Activity,不能在Test Case。
1
2
3
4
5
6
7
8
9
GlobalScope.launch (Dispatchers.Main) {
  // 切換至io
  withContext (Dispatchers.IO) {
    delay(1000)
    println("io")
  }
  // 切換回 main
  println("main")
}
順序執行
即便result2的delay秒數才500,但也是先執行完result1,才執行result2。
1
2
3
4
5
6
7
8
9
10
11
12
13
  @Test
  fun coroutine13() = runBlocking<Unit> {
    val result1 = withContext(Dispatchers.IO) {
      delay(1000)
      "result1"
    }
    println(result1)
    val result2 = withContext(Dispatchers.IO) {
      delay(500)
      "result2"
    }
    println(result2)
  }
result1
result2
非同步執行
非同步,我自己的記法是多個協程同時執行,不用等待其它協程執行完畢。
使用launch包住withContext,就可以變成非同步。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
  @Test
  fun coroutine15() = runBlocking {
    launch {
      val result1 = withContext(Dispatchers.IO) {
        delay(1000)
        "result1"
      }
      println(result1)
    }
    launch {
      val result2 = withContext(Dispatchers.IO) {
        delay(500)
        "result2"
      }
      println(result2)
    }
    println()
  }
result2
result1