Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
Kotlin Coroutine 基本的な使い方
Search
sutetotanuki
November 25, 2019
Programming
920
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
460
高速開発のためのコード整理術
sutetotanuki
1
1.1k
Next.js 16の新機能 Cache Components について
sutetotanuki
0
720
Vercel AI SDK を使って Next.js で AIアプリケーションを 作成する方法のご紹介
sutetotanuki
0
2k
WEBエンジニア向けAI活用入門
sutetotanuki
0
1.1k
ブラウザ上で実行され、 AIアシスタント付きデータベース postgres.new を触ってみた
sutetotanuki
0
600
今時のCookie事情
sutetotanuki
0
770
高速案件立ち上げで使われるマッハテンプレートのフロントエンド技術選定
sutetotanuki
2
2.2k
Core Web Vitals を改善する Next.js の機能群
sutetotanuki
1
2.7k
Other Decks in Programming
See All in Programming
フロントエンドUIフレームワークのこれまでとこれから
ssssota
5
2.5k
Swift愛好会と私(ウホーイ) / Swift Fan Club and Uhooi
uhooi
0
150
The Past, Present, and Future of Enterprise Java
ivargrimstad
0
290
XHTMLが残したもの
yosuke_furukawa
PRO
2
710
Security issues being discussed on Web Platforms
petamoriken
0
820
LoopHub - ローカルで動く GitHub で、AI と共同開発
jugyo
1
520
更なる可用性を求めて、5年間運用したKotlinのアプリケーションをGoでリプレイスする話
ken_tunc
0
130
AGENTS.md Is Not Enough:Build Skills, Don't Download Them
lx_t
0
110
The Good Stuff, Not the Slop: Engineering High-Quality Android Apps with Modern AI Tooling
danybony
1
240
XP祭りでしか伝わらないフリップネタ #xpjug
murabayashi
0
140
PHPプロジェクトの結合バランスを可視化する #php_night
kajitack
0
240
App Storeの外へ──日本のiOSサイドローディング入門 for iOSDC Japan 2026
yuukiw00w
0
190
Featured
See All Featured
"I'm Feeling Lucky" - Building Great Search Experiences for Today's Users (#IAC19)
danielanewman
230
23k
KATA
mclloyd
PRO
35
15k
Navigating Algorithm Shifts & AI Overviews - #SMXNext
aleyda
1
1.6k
Bridging the Design Gap: How Collaborative Modelling removes blockers to flow between stakeholders and teams @FastFlow conf
baasie
0
700
How to Talk to Developers About Accessibility
jct
2
540
Building AI with AI
inesmontani
PRO
1
1.2k
Side Projects
sachag
456
43k
A better future with KSS
kneath
240
18k
HTML-Aware ERB: The Path to Reactive Rendering @ RubyCon 2026, Rimini, Italy
marcoroth
4
640
Are puppies a ranking factor?
jonoalderson
2
3.9k
Practical Orchestrator
shlominoach
191
12k
Agile Leadership in an Agile Organization
kimpetersen
PRO
0
230
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 ෮ؼ ͢Δ
͝ਗ਼ௌ ͋Γ͕ͱ͏͍͟͝·ͨ͠