Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Kotlin Coroutine 基本的な使い方
Search
sutetotanuki
November 25, 2019
Programming
910
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Kotlin Coroutine 基本的な使い方
sutetotanuki
November 25, 2019
More Decks by sutetotanuki
See All by sutetotanuki
数案件を同時に進行するためのコンテキスト整理術
sutetotanuki
2
440
高速開発のためのコード整理術
sutetotanuki
1
1k
Next.js 16の新機能 Cache Components について
sutetotanuki
0
670
Vercel AI SDK を使って Next.js で AIアプリケーションを 作成する方法のご紹介
sutetotanuki
0
1.9k
WEBエンジニア向けAI活用入門
sutetotanuki
0
1.1k
ブラウザ上で実行され、 AIアシスタント付きデータベース postgres.new を触ってみた
sutetotanuki
0
580
今時のCookie事情
sutetotanuki
0
760
高速案件立ち上げで使われるマッハテンプレートのフロントエンド技術選定
sutetotanuki
2
2.1k
Core Web Vitals を改善する Next.js の機能群
sutetotanuki
1
2.7k
Other Decks in Programming
See All in Programming
今さら聞けない .NET CLI
htkym
0
190
Flow は今どうなっているか
mizdra
PRO
0
590
<title><a id="</title>君はこのHTMLをパースできるか"></a></title> #雑LT_study
pizzacat83
0
150
Building a Meta Ray-Ban display app
akkeylab
0
160
仕様駆動開発へのトライを機に チームに適合する手法を模索し続けている話
freee
PRO
0
540
自動化したのに回らないテスト運用の壁ーAI時代の品質責任と生産性
mfunaki
1
140
ドリフトを絶対に許さない(?)CDK運用 / CDK Ops with Zero Tolerance for Drifts (?)
akihisaikeda
1
190
Built Our Own Background Agent at LayerX
layerx
PRO
10
5.5k
AI時代のPHPer生存戦略 ~「言語、もうなんでもよくない?」に本気で向き合う~
vivion
0
660
komatsuna「分散システムにおけるバグ分析手法」
komatsunaqa
0
260
仕様駆動開発の消費期限
watany
20
8.4k
Lean は証明の正しさを確認するためだけのツールって思ってませんか?
inoueasei
1
160
Featured
See All Featured
Large-scale JavaScript Application Architecture
addyosmani
515
110k
Why Your Marketing Sucks and What You Can Do About It - Sophie Logan
marketingsoph
0
380
Winning Ecommerce Organic Search in an AI Era - #searchnstuff2025
aleyda
1
2.1k
How to build a perfect <img>
jonoalderson
1
5.9k
職位にかかわらず全員がリーダーシップを発揮するチーム作り / Building a team where everyone can demonstrate leadership regardless of position
madoxten
64
56k
B2B Lead Gen: Tactics, Traps & Triumph
marketingsoph
0
200
Principles of Awesome APIs and How to Build Them.
keavy
128
18k
Getting science done with accelerated Python computing platforms
jacobtomlinson
2
430
Exploring the Power of Turbo Streams & Action Cable | RailsConf2023
kevinliebholz
37
6.6k
Prompt Engineering for Job Search
mfonobong
0
400
New Earth Scene 8
popppiees
3
2.5k
A Modern Web Designer's Workflow
chriscoyier
698
190k
Transcript
,PUMJO$PSPVUJOF جຊతͳ͍ํ
w Ϋϥεϝιουגࣜձࣾ w $9ࣄۀ෦ॴଐ w "1*։ൃɺ"84ڥߏஙɺӡ༻ w /&8 "OESPJE
ࠓ͢͜ͱ w $PSPVUJOFͱ w $PSPVUJOFͷ͍Έͪ w جຊతͳ͍ํ w ࣮ྫू
$PSPVUJOFͱ
$PSPVUJOFͱ w ܰྔ5ISFBE w 5ISFBEͷΑ͏ʹѻ͑ͭ͋ͨΓʹඞཁͳϦ ιʔε͕5ISFBEΑΓ͍ܰ w ͨ͘͞ΜىಈͰ͖Δ
$PSPVUJOFͷ͍ಓ 6 ϝΠϯ 6* εϨουͰߦ͏ͱ69ΛଛͶΔ Մೳੑͷ͋Δॏ͍ͨॲཧΛผεϨουͰ࣮ߦ ͢Δ
ॏ͍ͨॲཧ 7 w *0όϯυͷॲཧ w ωοτϫʔΫΞΫηε w σΟεΫΞΫηε w $16όϯυͷॲཧ
w +40/ͷγϦΞϥΠζɺσγϦΞϥΠζ w Ϧετͷฒͼସ͑
جຊతͳ͍ํ
جຊతͳ͍ํ 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ͱ 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Ͱ࣮ߦ͞Ε ඇಉظʹॲཧ͞Ε͍ͯΔ
$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
$PSPVUJOF4DPQF
4DPQF֊ߏʹͰ͖Δ 4DPQFʹෳͷ$PSPVUJOFΛ࣋ͯΔ
$PSPVUJOF4DPQF fun main(args: Array<String>) = runBlocking { println("Start") GlobalScope.launch {
delay(1000) println("1") } println("2") println("End") } Start 2 End
$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ͷ είʔϓͰऴྃΛ·ͨͳ͍
$PSPVUJOF4DPQF fun main(args: Array<String>) = runBlocking { println("Start") launch {
delay(1000) println("1") } println("2") println("End") } Start 2 End 1
$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Λ࡞
$PSPVUJOFͱ fun main(args: Array<String>) = runBlocking { println("Start") launch {
delay(1000) println("1") } println("2") println("End") } Start 2 End 1
$PSPVUJOF %JTQBDIFST
$PSPVUJOF%JTQBDIFST 20 $PSPVUJOF͕Ͳͷ5ISFBEͰ࣮ߦ͞ΕΔ͔ ΛׂΓͯΔΈ
༻ҙ͞Ε͍ͯΔ%JTQBDIFST 21 εϨου ࠷దͳॲཧ .BJO ϝΠϯ UIΛมߋ͢ΔؔɻLiveDataͷߋ৽ *0 IOʹ࠷దԽ
ωοτϫʔΫɺσΟεΫΞΫηεͳͲ %FGBVMU όοΫάϥϯυ εϨουͷڞ༗ϓʔϧ CPUͷෛՙ͕େ͖͍ॲཧɻJSONղੳ Ϧετͷฒͼସ͑
$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
$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Λ࡞ ͢Δ
4VTQFOE
TVTQFOE 25 தஅɺ࠶։Ͱ͖ΔؔɻTVTQFOEؔ DPSPVUJOFɺ͘͠ผͷTVTQFOEؔ ͔Β͔͠ݺͳ͍
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
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 ΤϥʔʹͳΔ
TVTQFOE suspend fun getData(): ApiResponse { return callApi() } fun
main(args: Array<String>) = runBlocking { getData() } DPSPVUJOFΛىಈͦ͠ͷதͰݺͿͱ Τϥʔ͕ൃੜ͠ͳ͍
࣮༻ྫ
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 ?: "") } } }
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Λىಈ
ΤϥʔʹͳΒͳ͍Α͏ʹ͢Δ 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Ͱىಈ͢ΔΑ͏ʹࢦఆ
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Ͱर͑Δ
ίʔϧόοΫؔ $BMMCBDLΛ$PSPVUJOFͰͲ͏࣮͢Δͷ͔ Λ4USJQFͷ&QIFNFSBM,FZΛྫʹհ ͠·͢
ίʔϧόοΫؔ 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) } } ) }
4USJQFͷ &QIFNFSBM,FZ1SPWJEFS import androidx.annotation.Size interface EphemeralKeyProvider { fun createEphemeralKey( @Size(min
= 4) apiVersion: String, keyUpdateListener: EphemeralKeyUpdateListener ) }
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Λ͢
ίʔϧόοΫؔ 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ʹઃఆ
ίʔϧόοΫؔ 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 ෮ؼ ͢Δ
͝ਗ਼ௌ ͋Γ͕ͱ͏͍͟͝·ͨ͠