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
430
高速開発のためのコード整理術
sutetotanuki
1
1k
Next.js 16の新機能 Cache Components について
sutetotanuki
0
660
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
750
高速案件立ち上げで使われるマッハテンプレートのフロントエンド技術選定
sutetotanuki
2
2.1k
Core Web Vitals を改善する Next.js の機能群
sutetotanuki
1
2.7k
Other Decks in Programming
See All in Programming
複数の Claude Code が"放置"されてしまう問題をCLI ダッシュボードを自作して解決した話
sumihiro3
1
670
S3 を使うアプリケーションをローカル完結で動かすことに全力を注いでみた / Running S3 Apps Offline
contour_gara
0
400
Apache Hive: Toward a Cloud Native Lakehouse
okumin
0
180
2年かけて Deno に DOMMatrix を実装した話 / How I implemented DOMMatrix in Deno over two years
petamoriken
0
210
仕様駆動開発の消費期限
watany
17
7.3k
Terraform標準の組織で AWS CDKをどう使うか
mu7889yoon
1
490
Google Apps Script で Ruby を動かす
kawahara
0
140
テーブルをDELETEした
yuzneri
0
140
AWS DevOps AgentのAzure接続機能を検証して見えた活用法/Use Cases Verified for the AWS DevOps Agent's Azure Connectivity Feature
masakiokuda
1
220
PHP に部分適用が来るぞ!……ところで何それ?おいしいの? #phpcon / phpcon-2026
shogogg
0
600
言葉の格闘技のススメ~紙とペンと言葉から始める、キャリアの描き方~
progresscicada
2
140
PHP初心者セッション2026 〜生成AIでは見えない裏側を知る:今だからLAMPを通して仕組みを学ぶ〜
kashioka
0
870
Featured
See All Featured
The agentic SEO stack - context over prompts
schlessera
0
860
Have SEOs Ruined the Internet? - User Awareness of SEO in 2025
akashhashmi
0
410
Building the Perfect Custom Keyboard
takai
2
830
Crafting Experiences
bethany
1
240
Balancing Empowerment & Direction
lara
6
1.2k
RailsConf & Balkan Ruby 2019: The Past, Present, and Future of Rails at GitHub
eileencodes
141
35k
The AI Revolution Will Not Be Monopolized: How open-source beats economies of scale, even for LLMs
inesmontani
PRO
3
3.7k
How to Align SEO within the Product Triangle To Get Buy-In & Support - #RIMC
aleyda
2
1.8k
Rails Girls Zürich Keynote
gr2m
96
14k
Building Better People: How to give real-time feedback that sticks.
wjessup
370
20k
VelocityConf: Rendering Performance Case Studies
addyosmani
333
25k
The SEO Collaboration Effect
kristinabergwall1
1
520
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 ෮ؼ ͢Δ
͝ਗ਼ௌ ͋Γ͕ͱ͏͍͟͝·ͨ͠