Slide 1

Slide 1 text

,PUMJO$PSPVUJOF جຊతͳ࢖͍ํ

Slide 2

Slide 2 text

w Ϋϥεϝιουגࣜձࣾ w $9ࣄۀ෦ॴଐ w "1*։ൃɺ"84؀ڥߏஙɺӡ༻ w /&8 "OESPJE

Slide 3

Slide 3 text

ࠓ೔࿩͢͜ͱ w $PSPVUJOFͱ͸ w $PSPVUJOFͷ࢖͍Έͪ w جຊతͳ࢖͍ํ w ࣮ྫू

Slide 4

Slide 4 text

$PSPVUJOFͱ͸

Slide 5

Slide 5 text

$PSPVUJOFͱ͸ w ܰྔ5ISFBE w 5ISFBEͷΑ͏ʹѻ͑ͭ͋ͨΓʹඞཁͳϦ ιʔε͕5ISFBEΑΓ΋͍ܰ w ͨ͘͞ΜىಈͰ͖Δ

Slide 6

Slide 6 text

$PSPVUJOFͷ࢖͍ಓ 6 ϝΠϯ 6* εϨουͰߦ͏ͱ69ΛଛͶΔ
 Մೳੑͷ͋Δॏ͍ͨॲཧΛผεϨουͰ࣮ߦ ͢Δ

Slide 7

Slide 7 text

ॏ͍ͨॲཧ 7 w *0ό΢ϯυͷॲཧ w ωοτϫʔΫΞΫηε w σΟεΫΞΫηε w $16ό΢ϯυͷॲཧ w +40/ͷγϦΞϥΠζɺσγϦΞϥΠζ w Ϧετͷฒͼସ͑

Slide 8

Slide 8 text

جຊతͳ࢖͍ํ

Slide 9

Slide 9 text

جຊతͳ࢖͍ํ fun main(args: Array) { println("Start") GlobalScope.launch { delay(1000) println("1") } println("2") println("End") Thread.sleep(2000) } Start 2 End 1

Slide 10

Slide 10 text

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

Slide 11

Slide 11 text

$PSPVUJOFͱ͸ fun main(args: Array) { println("Start") GlobalScope.launch { delay(1000) println("1") } println("2") println("End") Thread.sleep(2000) } Start 2 End 1 $PSPVUJOF #VJMEFS $PSPVUJOF 4DPQF

Slide 12

Slide 12 text

$PSPVUJOF4DPQF

Slide 13

Slide 13 text

4DPQF͸֊૚ߏ଄ʹͰ͖Δ 4DPQFʹෳ਺ͷ$PSPVUJOFΛ࣋ͯΔ

Slide 14

Slide 14 text

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

Slide 15

Slide 15 text

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

Slide 16

Slide 16 text

$PSPVUJOF4DPQF fun main(args: Array) = runBlocking { println("Start") launch { delay(1000) println("1") } println("2") println("End") } Start 2 End 1

Slide 17

Slide 17 text

$PSPVUJOFͱ͸ fun main(args: Array) = 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Λ࡞੒

Slide 18

Slide 18 text

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

Slide 19

Slide 19 text

$PSPVUJOF %JTQBDIFST

Slide 20

Slide 20 text

$PSPVUJOF%JTQBDIFST 20 $PSPVUJOF͕Ͳͷ5ISFBEͰ࣮ߦ͞ΕΔ͔ ΛׂΓ౰ͯΔ࢓૊Έ

Slide 21

Slide 21 text

༻ҙ͞Ε͍ͯΔ%JTQBDIFST 21 εϨου ࠷దͳॲཧ .BJO ϝΠϯ UIΛมߋ͢Δؔ਺ɻLiveDataͷߋ৽ ౳ *0 IOʹ࠷దԽ ωοτϫʔΫɺσΟεΫΞΫηεͳͲ %FGBVMU όοΫάϥ΢ϯυ
 εϨουͷڞ༗ϓʔϧ CPUͷෛՙ͕େ͖͍ॲཧɻJSONղੳ ΍Ϧετͷฒͼସ͑౳

Slide 22

Slide 22 text

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

Slide 23

Slide 23 text

$PSPVUJOF%JTQBDIFST fun main(args: Array) = runBlocking { withContext(Dispatchers.IO) { println("IO: ${Thread.currentThread().id}") } println("Main: ${Thread.currentThread().id}") } IO: 11 Main: 1 $PSPVUJOF4DPQFͷUIJTMBVODI ϝιουͰࢠ$PSPVUJOF4DPQFΛ࡞੒ ͢Δ

Slide 24

Slide 24 text

4VTQFOE

Slide 25

Slide 25 text

TVTQFOE 25 தஅɺ࠶։Ͱ͖Δؔ਺ɻTVTQFOEؔ਺͸ DPSPVUJOFɺ΋͘͠͸ผͷTVTQFOEؔ਺ ͔Β͔͠ݺ΂ͳ͍

Slide 26

Slide 26 text

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

Slide 27

Slide 27 text

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

Slide 28

Slide 28 text

TVTQFOE suspend fun getData(): ApiResponse { return callApi() } fun main(args: Array) = runBlocking { getData() } DPSPVUJOFΛىಈͦ͠ͷதͰݺͿͱ Τϥʔ͕ൃੜ͠ͳ͍

Slide 29

Slide 29 text

࣮༻ྫ

Slide 30

Slide 30 text

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() val userName = MutableLiveData() fun getUser() { viewModelScope.launch { response.value = callApi(userName.value ?: "") } } }

Slide 31

Slide 31 text

7JFX.PEFMͰ࢖͏ class MainViewModel : ViewModel() { val response = MutableLiveData() val userName = MutableLiveData() fun getUser() { viewModelScope.launch { response.value = callApi(userName.value ?: "") } } } ϝΠϯεϨουͰΠϯλʔωοτΞΫηε ͢ΔͨΊΤϥʔʹͳΔ WJFX.PEFMͷϥΠϑαΠΫϧͰ؅ཧ͞ΕΔ WJFX.PEFM4DPQFͷ $PSPVUJOF#VJMEFSͰ$PSPVUJOFΛىಈ

Slide 32

Slide 32 text

ΤϥʔʹͳΒͳ͍Α͏ʹ͢Δ 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Ͱىಈ͢ΔΑ͏ʹࢦఆ

Slide 33

Slide 33 text

class MainViewModel : ViewModel() { val response = MutableLiveData() val userName = MutableLiveData("sutetotanuki") val error = MutableLiveData() fun getGithubUser() { viewModelScope.launch { try { response.value = callApi(userName.value ?: "") } catch (e: Throwable) { error.value = e.message } } } } Τϥʔॲཧ TVTQFOEؔ਺ͷΤϥʔ΋ USZDBUDIͰर͑Δ

Slide 34

Slide 34 text

ίʔϧόοΫؔ਺ $BMMCBDLΛ$PSPVUJOFͰͲ͏࣮૷͢Δͷ͔ Λ4USJQFͷ&QIFNFSBM,FZΛྫʹ঺հ ͠·͢

Slide 35

Slide 35 text

ίʔϧόοΫؔ਺ override suspend fun initSession() = suspendCoroutine { 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) } } ) }

Slide 36

Slide 36 text

4USJQFͷ &QIFNFSBM,FZ1SPWJEFS import androidx.annotation.Size interface EphemeralKeyProvider { fun createEphemeralKey( @Size(min = 4) apiVersion: String, keyUpdateListener: EphemeralKeyUpdateListener ) }

Slide 37

Slide 37 text

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Λ౉͢

Slide 38

Slide 38 text

ίʔϧόοΫؔ਺ suspend fun initSession() = suspendCoroutine { 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ʹઃఆ

Slide 39

Slide 39 text

ίʔϧόοΫؔ਺ suspend fun initSession() = suspendCoroutine { 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 ෮ؼ ͢Δ

Slide 40

Slide 40 text

͝ਗ਼ௌ ͋Γ͕ͱ͏͍͟͝·ͨ͠