Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Kotlin Coroutine 基本的な使い方

Avatar for sutetotanuki sutetotanuki
November 25, 2019

Kotlin Coroutine 基本的な使い方

Avatar for sutetotanuki

sutetotanuki

November 25, 2019
Tweet

More Decks by sutetotanuki

Other Decks in Programming

Transcript

  1. $PSPVUJOFͱ͸ fun main(args: Array<String>) { println("Start") GlobalScope.launch { delay(1000) println("1")

    } println("2") println("End") Thread.sleep(2000) } Start 2 End 1 $PSPVUJOFͰ࣮ߦ͞Ε ඇಉظʹॲཧ͞Ε͍ͯΔ
  2. $PSPVUJOFͱ͸ fun main(args: Array<String>) { println("Start") GlobalScope.launch { delay(1000) println("1")

    } println("2") println("End") Thread.sleep(2000) } Start 2 End 1 $PSPVUJOF #VJMEFS $PSPVUJOF 4DPQF
  3. $PSPVUJOF4DPQF fun main(args: Array<String>) = runBlocking { println("Start") GlobalScope.launch {

    delay(1000) println("1") } println("2") println("End") } Start 2 End
  4. $PSPVUJOF4DPQF fun main(args: Array<String>) = runBlocking { println("Start") GlobalScope.launch {

    delay(1000) println("1") } println("2") println("End") } Start 2 End (MPCBM4DPQF ʹͳΔͨΊSVO#MPDLJOHͷ είʔϓͰ͸ऴྃΛ·ͨͳ͍
  5. $PSPVUJOF4DPQF fun main(args: Array<String>) = runBlocking { println("Start") launch {

    delay(1000) println("1") } println("2") println("End") } Start 2 End 1
  6. $PSPVUJOFͱ͸ fun main(args: Array<String>) = runBlocking { println("Start") launch {

    delay(1000) println("1") } println("2") println("End") } Start 2 End 1 SVO#MPDLJOHͷείʔϓͷUIJT͸ $PSPVUJOF4DPQF SVO#MPDLJOHͷ4DPQFͷMBVODIϝιουͰ ࢠ$PSPVUJOF4DPQFΛ࡞੒
  7. $PSPVUJOFͱ͸ fun main(args: Array<String>) = runBlocking { println("Start") launch {

    delay(1000) println("1") } println("2") println("End") } Start 2 End 1
  8. ༻ҙ͞Ε͍ͯΔ%JTQBDIFST 21 εϨου ࠷దͳॲཧ .BJO ϝΠϯ UIΛมߋ͢Δؔ਺ɻLiveDataͷߋ৽ ౳ *0 IOʹ࠷దԽ

    ωοτϫʔΫɺσΟεΫΞΫηεͳͲ %FGBVMU όοΫάϥ΢ϯυ
 εϨουͷڞ༗ϓʔϧ CPUͷෛՙ͕େ͖͍ॲཧɻJSONղੳ ΍Ϧετͷฒͼସ͑౳
  9. $PSPVUJOF%JTQBDIFST fun main(args: Array<String>) = runBlocking { withContext(Dispatchers.IO) { delay(1000)

    println("IO: ${Thread.currentThread().id}") } println("Main: ${Thread.currentThread().id}") } IO: 11 Main: 1
  10. $PSPVUJOF%JTQBDIFST fun main(args: Array<String>) = runBlocking { withContext(Dispatchers.IO) { println("IO:

    ${Thread.currentThread().id}") } println("Main: ${Thread.currentThread().id}") } IO: 11 Main: 1 $PSPVUJOF4DPQFͷUIJTMBVODI ϝιουͰࢠ$PSPVUJOF4DPQFΛ࡞੒ ͢Δ
  11. TVTQFOE suspend fun getData(): ApiResponse { return callApi() } fun

    main(args: Array<String>) { getData() } Suspend function 'getData' should be called only from a coroutine or another suspend function
  12. TVTQFOE suspend fun getData(): ApiResponse { return callApi() } fun

    main(args: Array<String>) { getData() } Suspend function 'getData' should be called only from a coroutine or another suspend function ΤϥʔʹͳΔ
  13. TVTQFOE suspend fun getData(): ApiResponse { return callApi() } fun

    main(args: Array<String>) = runBlocking { getData() } DPSPVUJOFΛىಈͦ͠ͷதͰݺͿͱ Τϥʔ͕ൃੜ͠ͳ͍
  14. 7JFX.PEFMͰ࢖͏ fun callApi(name: String): UserResponseBody { val client = OkHttpClient()

    val request = Request.Builder() .url("https://api.github.com/users/$name") .build() client.newCall(request).execute().use {response -> return Gson().fromJson(response.body?.string(), UserResponseBody::class.java) } } class MainViewModel : ViewModel() { val response = MutableLiveData<UserResponseBody>() val userName = MutableLiveData<String>() fun getUser() { viewModelScope.launch { response.value = callApi(userName.value ?: "") } } }
  15. 7JFX.PEFMͰ࢖͏ class MainViewModel : ViewModel() { val response = MutableLiveData<UserResponseBody>()

    val userName = MutableLiveData<String>() fun getUser() { viewModelScope.launch { response.value = callApi(userName.value ?: "") } } } ϝΠϯεϨουͰΠϯλʔωοτΞΫηε ͢ΔͨΊΤϥʔʹͳΔ WJFX.PEFMͷϥΠϑαΠΫϧͰ؅ཧ͞ΕΔ WJFX.PEFM4DPQFͷ $PSPVUJOF#VJMEFSͰ$PSPVUJOFΛىಈ
  16. ΤϥʔʹͳΒͳ͍Α͏ʹ͢Δ suspend fun callApi(name: String): UserResponseBody = withContext(Dispatchers.IO){ val client

    = OkHttpClient() val request = Request.Builder() .url("https://api.github.com/users/$name") .build() client.newCall(request).execute().use {response -> Gson().fromJson(response.body?.string(), UserResponseBody::class.java) } } TVTQFOEؔ਺ʹ͢Δ %JTQBDIFST*0Ͱىಈ͢ΔΑ͏ʹࢦఆ
  17. class MainViewModel : ViewModel() { val response = MutableLiveData<UserResponseBody>() val

    userName = MutableLiveData<String>("sutetotanuki") val error = MutableLiveData<String>() fun getGithubUser() { viewModelScope.launch { try { response.value = callApi(userName.value ?: "") } catch (e: Throwable) { error.value = e.message } } } } Τϥʔॲཧ TVTQFOEؔ਺ͷΤϥʔ΋ USZDBUDIͰर͑Δ
  18. ίʔϧόοΫؔ਺ override suspend fun initSession() = suspendCoroutine<Unit> { con ->

    CustomerSession.initCustomerSession( context, object : EphemeralKeyProvider { override fun createEphemeralKey( apiVersion: String, keyUpdateListener: EphemeralKeyUpdateListener ) { val ephemeralKeyBody = runBlocking { api.issueEphemeralKey(EphemeralKeyRequest(apiVersion)) } keyUpdateListener.onKeyUpdate(ephemeralKeyBody.string()) con.resume(Unit) } } ) }
  19. 4USJQFͷ &QIFNFSBM,FZ1SPWJEFS import androidx.annotation.Size interface EphemeralKeyProvider { fun createEphemeralKey( @Size(min

    = 4) apiVersion: String, keyUpdateListener: EphemeralKeyUpdateListener ) } BQJ7FSTJPOΛ&QIFNFSBM,FZΛੜ੒͢ ΔαʔόʔαΠυͷ"1*ʹΘͨ͢ LFZ6QEBUF-JTUFOFSʹ"1*͕ੜ੒ͨ͠ &QIFNFSBM,FZΛ౉͢
  20. ίʔϧόοΫؔ਺ suspend fun initSession() = suspendCoroutine<Unit> { con -> CustomerSession.initCustomerSession(

    context, object : EphemeralKeyProvider { override fun createEphemeralKey( apiVersion: String, keyUpdateListener: EphemeralKeyUpdateListener ) { val ephemeralKeyBody = runBlocking { api.issueEphemeralKey(EphemeralKeyRequest(apiVersion)) } keyUpdateListener.onKeyUpdate(ephemeralKeyBody.string()) con.resume(Unit) } } ) } BQJ͕TVTQFOEؔ਺Ͱ࣮૷͞Ε͍ͯΔͷͰ SVO#MPDLJOHͰݺͼͩ͠ "1*ͷϨεϙϯεΛ-JTUFOFSʹઃఆ
  21. ίʔϧόοΫؔ਺ suspend fun initSession() = suspendCoroutine<Unit> { con -> CustomerSession.initCustomerSession(

    context, object : EphemeralKeyProvider { override fun createEphemeralKey( apiVersion: String, keyUpdateListener: EphemeralKeyUpdateListener ) { val ephemeralKeyBody = runBlocking { api.issueEphemeralKey(EphemeralKeyRequest(apiVersion)) } keyUpdateListener.onKeyUpdate(ephemeralKeyBody.string()) con.resume(Unit) } } ) } -JTUFOFSʹ஋Λ౉ͤͨͷͰ SFTVNF ෮ؼ ͢Δ