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

DevFest 2019 Songdo - RxJava and Coroutine

TaeHwan
November 30, 2019

DevFest 2019 Songdo - RxJava and Coroutine

DevFest 2019 Songdo
RxJava and Coroutunes.

TaeHwan

November 30, 2019
Tweet

More Decks by TaeHwan

Other Decks in Programming

Transcript

  1. Threadۆ? Coroutines ੉ۆ? ReactivieXۆ? - RxJava/RxKotlin/RxAndroid RxJava৬ Coroutinesਸ ೣԋ ࢎਊೞ۰ݶ?

    ೣ੿ ౵ӝ > ӝࠄ ѐ֛ਸ ࡅܰѱ ঌইࠁҊ, ઱੄ೡ ղਊਸ ਤ઱۽ ׮ܘ׮ য়ט ঌইࠅ ղਊ
  2. Rx੄ ݆ࣻ਷ operatorܳ ׮ܖ૑ ঋח׮. Coroutines੄ ׮নೠ ੽Ӕ ߑߨਸ ׮ܖ૑ח

    ঋח׮ য়ט ঌইࠁ૑ ঋਸ ղਊ ઱੄ : ӝ؀ೠ ࠗ࠙਷ হਸ ࣻ ੓׮
  3. Threadח Processীࢲ ੘সਸ ೞӝ ਤೠ ױਤ Thread { /* Block

    */ } ഋక۽ ҳഅ Thread? Thread { Thread.sleep(500L) Handler(Looper.getMainLooper()).post { Toast.makeText( this, "lazy Toast!", Toast.LENGTH_SHORT) .show() } }.start()
  4. RxJava - Threadܳ ખ ؊ औҊ, ಞೞѱ ॳӝ ਤೠ operator

    ݽ਺ ഋక - Observer pattern, Iterator pattern, Functional programming Ѿ೤ Coroutines - Assembly languageীࢲ ࢎਊغ঻؍ Routine ѐ֛ - JVM ਤীࢲח Threadܳ ࢎਊ೧ঠ ೠ׮ * JVM (Java virtual machine) JVMীࢲ ز੘ೞ۰ݶ Threadо ೙ਃೞ׮
  5. Asynchronous or non-blocking programming is the new reality. Observer pattern

    ࢎਊਸ ઴ੌ ࣻ ੓חؘ, return ೧઴ ٸө૑ ؀ӝ दఅ׮ RxJava ࠁ׮ ҳܾ ࣻ ੓׮ ॶࣻ۾ য۵׮(Error ୊ܻۄ؍о, ղо ॳח ѱ ݏחо?ۄ؍о) Coroutines? https://kotlinlang.org/docs/reference/coroutines-overview.html
  6. ഐ୹ೞח ೣࣻ੄ returnਸ ӝ׮ܻҊ, যڌѱ ӝ׮ܾө? suspend fun loadData(): Item

    { // load data delay(500) return Item() } @Test fun test() = runBlocking { val item = loadData() } ੉ ਽׹ чਸ о૑Ҋ ୊ܻೡ ࣻ ੓׮.
  7. An API for asynchronous programming with observable streams 3о૑ ഋకܳ

    Ѿ೤ೠ observable streams - Observable pattern - Iterator pattern - Functional programming Android - RxJava - RxAndroid - RxKotlin ReactiveX? http://reactivex.io/
  8. Javaܳ ਤೠ RxJava ۄ੉࠳۞ܻ RxJava 1.x : 2018֙ 12ਘ 31ੌ

    ੉޷ ઙܐغ঻׮. RxJava 2.x : 2020֙ 12ਘ 31ੌө૑ ࠁউ ಁ஖ ૑ਗೠ׮. RxJava 3.x : RC 5ө૑ աৡ ࢚కۄ ҍ ߓನೡ٠ೞ׮. RxJava https://github.com/ReactiveX/RxJava
  9. RxJava੄ ੌࠗ ഛ੢ ೣࣻܳ ઁҕ combineLatest zip withLatestFrom ١… disposableਸ

    ਤೠ ഛ੢ ೣࣻ ઁҕ > RxKotlin਷ RxJava হ੉ ز੘ೞ૑ ঋח׮. RxKotlin /** * disposable += observable.subscribe() */ operator fun CompositeDisposable.plusAssign(disposable: Disposable) { add(disposable) } fun Disposable.addTo(compositeDisposable: CompositeDisposable): Disposable = apply { compositeDisposable.add(this) } https://github.com/ReactiveX/RxKotlin
  10. Android Schedulerܳ ನೣೞҊ ੓׮ RxJavaܳ ನೣೞҊ ੓׮ Rxjava ߡ੹ਸ ߹ب

    ݺदೞח Ѧ ୶ୌೞҊ ੓׮. RxAndroid Observable.just("one", "two", "three", "four", "five") .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe {/* an Observer */} https://github.com/ReactiveX/RxAndroid
  11. RxJava - Observable patternਵ۽ ҳة - ҳة റ ٜযয়ח dataܳ

    streams ഋక۽ ղ۰ࠁմ׮. - ઺р઺р ؘ੉ఠо ߸ജغח Ѧ Streamsਸ ా೧ ഛੋ оמೞ׮. - Coroutines - ־ҳա ইח ೣࣻܳ ഐ୹ೞҊ, return੉ য়ӝ ੹ө૑ ӝ׮ܽ׮. - ୊ܻо ՘ա return ೠ ؘ੉ఠܳ о૑Ҋ ׮਺ ୊ܻܳ ೡ ࣻ ੓׮. RxJava vs Coroutines
  12. ࠺زӝ ୊ܻ੄ ҙ੼ীࢲ ࠺Үೡ ࣽ ੓׮ ؘ੉ఠ੄ ൒ܴਸ ӝળਵ۽ ೠ׮ݶ

    ইפ׮. RxJava৬ Coroutinesਸ ࠺Үೞח ѱ ݏਸө? > Coroutines 1.3ী ୶оೠ Flow৬ ࠺Үೞח ѱ ખ ؊ ݏ׮
  13. Flowח Coroutines 1.3ীࢲ ੿धਵ۽ ࢎਊ оמೞ׮ A cold asynchronous data

    stream that sequentially emits values and completes normally or with an exception. Flow fun call(): Flow<Int> = flow { // flow builder for (i in 1..3) { delay(100) // pretend we are doing something useful here emit(i) // emit next value } } @Test fun runBlockingTest() = runBlocking { // Collect the flow foo().collect { value -> println(value) } } https://kotlinlang.org/docs/reference/coroutines/flow.html
  14. GlobalScope.launch ࢤࢿ CoroutineScope().launch ࢤࢿ launch۽ Dispatcher ߸҃ withContext੄ ࢎਊ Flowীࢲ

    ೲਊೞ૑ ঋח ಁఢ fun foo(): Flow<Int> = flow { println("Flow started") for (i in 1..3) { delay(100) emit(i) coroutineScope { emit(100) } } } ੉ ҃਋ח ೲਊ೧ਃ
  15. दաܻয় E-Mailҗ passwordܳ ੑ۱߉ח׮ E-Mailҗ Passwordܳ ݽف ੑ۱߉ӝ ੹ীח ߡౡ

    ࠺ഝࢿച E-Mailҗ Password ઺ ೞա݅ ੑ۱غ঻ਵݶ ࠺ഝࢿച ݽٚ ੑ۱੉ ՘աݶ Login ߡౡ ഝࢿച ੑ۱ ੹ ੑ۱ റ
  16. Subject ࢎਊ email/passwordܳ ߉ਸ BehaviorSubject ࢤࢿ email/password ݽف ߉ওਸ ٸ

    ୊ܻೡ ੉߮౟ ೞա ؊ ୶о RxJava۽ ҳഅ private val emailSubject = BehaviorSubject.create<String>() private val passwordSubject = BehaviorSubject.create<String>() private val enableLoginSubject = BehaviorSubject.create<Boolean>()
  17. emailҗ password ੑ۱ਸ ؀ӝೡ combineLatest email/passwordо ੑ۱غ঻ਸ ٸ, isNotEmpty()ܳ ୓௼ೠ׮

    ӒܻҊ Ӓ ୊ܻ ੿ࠁܳ enableLoginSubject۽ ֈѹળ׮. RxJava۽ ҳഅ Observable.combineLatest<String, String, Boolean>( emailSubject, passwordSubject, BiFunction { email, password -> email.isNotEmpty() && password.isNotEmpty() }) .subscribe { enableLoginSubject.onNext(it) }
  18. enableLoginSubject੄ ਽׹ਸ Coroutinesਵ۽ ߉ইࠁ੗ Observer patternਸ return ഋక۽ ߉ਵ۰ݶ? ഛੋ਷

    Coroutineਸ ഝਊೞ੗ public suspend inline fun <T> suspendCancellableCoroutine( crossinline block: (CancellableContinuation<T>) -> Unit ): T = suspendCoroutineUninterceptedOrReturn { uCont -> val cancellable = CancellableContinuationImpl(uCont.intercepted(), resumeMode = MODE_CANCELLABLE) block(cancellable) cancellable.getResult() } suspendCancellableCoroutine
  19. ഛੋ਷ Coroutineਸ ഝਊೞ੗ @ExperimentalCoroutinesApi @InternalCoroutinesApi @Test fun test() = runBlocking

    { // ৈӝী ׸ח׮ } val ret = suspendCancellableCoroutine<Boolean> { continuation -> // ৈӝী RxJavaܳ ҳഅ continuation.invokeOnCancellation { try { cancel() } catch (e: Exception) { println(e) } } } assert(ret) enableLoginSubject .subscribeOn(Schedulers.io()) .subscribe({ continuation.resumeWith(kotlin.runCatching { it }) }, { continuation.resumeWithException(it) })
  20. RxJava৬ Coroutineਸ ೣԋ ॳݶ? Coroutineਸ ੸ਊೞҊ र঻׮ݶ ب੹ оמ ݽف

    ߸҃ೞח Ѥ য۵Ҋ, Coroutineਸ ࢎਊ೧ࠁҊ र঻׮ݶ Coroutine੉ ݽٚ Ѧ ઁҕೞ૑ח ঋח׮. ੉۠ ۄ੉࠳۞ܻח https://github.com/Kotlin/kotlinx.coroutines/tree/ master/reactive/kotlinx-coroutines-rx2 ীоݶ ੓׮
  21. Ӓۢ Coroutineਵ۽ ҳഅೞ۰ݶ? Coroutine੄ Message ୊ܻ ߑधਵ۽ ೧ࠅ ࣽ ੓׮.

    channels or actors channels : https://kotlinlang.org/docs/reference/ coroutines/channels.html actors : https://kotlinlang.org/docs/reference/ coroutines/shared-mutable-state-and- concurrency.html#actors
  22. Android Unit Test - ೣ੿ਸ ٜ݅੗ fun call(): Flow<Int> =

    flow { for (i in 1..3) { delay(100) emit(i) // emit next value } } fun runBlockingTest() { GlobalScope.launch { launch { for (k in 1..3) { println("I'm not blocked $k") delay(100) } } foo().collect { value -> println(value) } } } @Test fun callTest() { println("subroutines") runBlockingTest() // Coroutines println("subroutines") }
  23. Android Unit Test - ખ ؊ ࠅө? fun call(): Flow<Int>

    = flow { for (i in 1..3) { delay(100) emit(i) // emit next value } } fun runBlockingTest() { GlobalScope.launch { launch { for (k in 1..3) { println("I'm not blocked $k") delay(100) } } foo().collect { value -> println(value) } } } @Test fun callTest() { println("subroutines") runBlockingTest() // Coroutines println("subroutines") }
  24. Android Unit Test - ੉ Ѿҗ ч਷ ަө? fun call():

    Flow<Int> = flow { for (i in 1..3) { delay(100) emit(i) // emit next value } } fun runBlockingTest() { GlobalScope.launch { launch { for (k in 1..3) { println("I'm not blocked $k") delay(100) } } foo().collect { value -> println(value) } } } @Test fun callTest() { println("subroutines") runBlockingTest() // Coroutines println("subroutines") } Ѿҗח Subroutines Subroutines ܳ ୹۱ೞҊ ՘դ׮.
  25. Coroutine਷ ೣࣻ returnਸ ӝ׮ܽ׮. Coroutine block উীࢲ ݅ ৵? fun

    runBlockingTest() { GlobalScope.launch { // ৈӝח ௏ܖ౯ উ - ৈӝࢲח ௏ܖ౯ ੉߮౟ܳ ߉ਸ ࣻ ੓׮ } } @Test fun callTest() { // ৈӝח ௏ܖ౯੉ ইջ println("subroutines") runBlockingTest() // Coroutines println("subroutines") // ৈӝח ௏ܖ౯੉ ইջ - ௏ܖ౯ ੉߮౟ܳ ߉૑ ޅೠ׮ } Listener ١۾೮૑݅ Listener ߆ীח ৵ ੉߮౟о য়૑ ঋભ? > ߉ਸ Ҕ੉ ࢎۄ઎׮ > زੌೠ ߑߨ੉ۄݶ Coroutineب эইਃ
  26. Runs a new coroutine and blocks the current thread interruptibly

    until its completion. This function should not be used from a coroutine. It is designed to bridge regular blocking code to libraries that are written in suspending style, to be used in main functions and in tests. runBlocking? https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/run-blocking.html
  27. ೧Ѿ fun call(): Flow<Int> = flow { for (i in

    1..3) { delay(100) emit(i) // emit next value } } fun runBlockingTest() { GlobalScope.launch { launch { for (k in 1..3) { println("I'm not blocked $k") delay(100) } } foo().collect { value -> println(value) } } } @Test fun callTest() { println("subroutines") runBlockingTest() // Coroutines println("subroutines") } subroutines Flow started I'm not blocked 1 … 1 … 100 I'm not blocked 2 … 2 … 100 I'm not blocked 3 … 3 … 100 subroutines
  28. runBlocking਷ Unit Testীࢲ ݅ ࢎਊ೧ঠ ೠ׮ Thread ઙܨܳ ૑੿ೞ૑ ঋওӝী

    UI Threadীࢲ ز੘ UIীࢲ runBlocking ࢎਊद ANR(Application Not Responding) ߊࢤ runBlocking਷ Unit testীࢲ ݅ public fun <T> runBlocking( context: CoroutineContext = EmptyCoroutineContext, block: suspend CoroutineScope.() -> T): T { // ࢤۚ }
  29. CoroutineScopeਸ ࢚ࣘ ߉ই ҳഅ೧ঠ ೠ׮. ૒੽ ҳഅदח lifecycleী ٮܲ cancel()ਸ

    ೧ঠೠ׮. AAC ViewModel/LiveDataਸ ࢎਊೡ ࣻ ੓׮ Androidীࢲ ੜ ࢎਊೞӝ class MyViewModel: ViewModel() { init { viewModelScope.launch { // Coroutine that will be canceled when the ViewModel is cleared. } } } val user: LiveData<User> = liveData { val data = database.loadUser() // loadUser is a suspend function. emit(data) }
  30. try/catchਸ ੉ਊೠ ী۞ ୊ܻ Error ୊ܻ launch { try {

    throw Exception("Error!!!!") } catch (e: Exception) { } }
  31. CoroutineExceptionHandler ࢎਊ coroutineContext৬ throwable ੿ࠁܳ ੹׳ CoroutineScopeী Scheduler + exceptionHanderܳ

    ૑੿ ખ ؊ જ਷ Exception ୊ܻ val exceptionHandler = CoroutineExceptionHandler { coroutineContext, throwable -> // Error ୊ܻ } CoroutineScope(exceptionHandler).launch { throw Exception("Error!!!!") }.invokeOnCompletion { if (ҕా੸ੋ য়ܨ ୊ܻ റী ژ ୊ܻо ೙ਃೞ׮ݶ?) { it?.printStackTrace() } }
  32. Coroutines જਵפ ݋Ԉ ॳࣁਃ. Ҋ޹਷ ݆੉ ೙ਃ. RxJavaܳ ࠂ੟ೞѱ ॳח

    Ѫࠁ׮ח ੍ӝ ए਍ ௏٘ оةࢿ Androidীࢲח ԙ! lifecycleਸ ٮۄ઱ࣁਃ. 5.x؀੄ ࢖ࢿ ӝӝীࢲ ޙઁо ੓חؘ … Lifecycle ੜ ٮܰݶ ҡଳ਺ > Lifecycleਸ ҙܻೞӝ ൨ٜ׮ݶ LiveData৬ ೣԋ ॳݶ ௾ ޙઁ হ਺ > ੉ ޙઁח ݽٚ Threadীࢲ زੌೞѱ ߊࢤೞח ޙઁۄࢲ ௏ܖ౯ ݅੄ ޙઁח ইש Ӓېࢲ?