Slide 1

Slide 1 text

MAKING ONACTIVITYRESULT MORE EASY SHIBUYA.APK #22 2018.02.06 HIROSHI KUROKAWA
 FABLIC, INC.

Slide 2

Slide 2 text

WHY ONACTIVITYRESULT IS SOMETIMES CUMBERSOME ‣ Android Framework is really great ‣ Activity Stack is well designed ‣ … But sometimes starting an Activity and receiving its result is a bit cumbersome, isn’t it?

Slide 3

Slide 3 text

WHY ONACTIVITYRESULT IS SOMETIMES CUMBERSOME override fun onActivityResult( requestCode: Int, resultCode: Int, data: Intent? ) { super.onActivityResult(requestCode, resultCode, data) when(requestCode) { REQ_CODE_LOGIN -> handleLoginResult(resultCode) REQ_CODE_PURCHASE -> handlePurchaseResult(resultCode, data) } } `when` statement can 
 be long

Slide 4

Slide 4 text

WHY ONACTIVITYRESULT IS SOMETIMES CUMBERSOME fun onPurchaseClicked(view: View) { val itemId = 42 if (isNotLoggedIn()) { startActivityForResult(LoginActivity.newIntent(this), REQ_CODE_LOGIN) } else { startActivityForResult(ConfirmationActivity.newIntent(this, itemId), REQ_CODE_PURCHASE) } } override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { super.onActivityResult(requestCode, resultCode, data) when(requestCode) { REQ_CODE_LOGIN -> handleLoginResult(resultCode) REQ_CODE_PURCHASE -> handlePurchaseResult(resultCode, data) } } startActivity and onActivityResult
 are not close to each other

Slide 5

Slide 5 text

ANY SOLUTION? ¯\_(π)_/¯

Slide 6

Slide 6 text

1. Annotation Processor

Slide 7

Slide 7 text

ANNOTATION PROCESSOR

Slide 8

Slide 8 text

ANNOTATION PROCESSOR override fun onActivityResult( requestCode: Int, resultCode: Int, data: Intent? ) { super.onActivityResult(requestCode, resultCode, data) ActivityResult .onResult(requestCode, resultCode, data) .into(this) }

Slide 9

Slide 9 text

ANNOTATION PROCESSOR @OnActivityResult(requestCode = REQ_CODE_LOGIN) fun handleLoginResult(resultCode: Int) { … } @OnActivityResult(requestCode = REQ_CODE_PURCHASE) fun handlePurchaseResult(resultCode: Int, data: Intent?) { … }

Slide 10

Slide 10 text

ANNOTATION PROCESSOR ‣ Simple ‣ Less boilerplate code ‣ But there is still a distance between startActivity and onActivityResult

Slide 11

Slide 11 text

EXAMPLE: RESUMING THE LAST ACTION 1. A user tries to buy a product 2. She is redirected to the login screen 3. I want her to resume the purchase when she backs to the previous screen

Slide 12

Slide 12 text

YOU HAVE TO ‣ Remember the last context ‣ Resume the process when user backs to the screen ‣ Handle all the possible cases Not that easy

Slide 13

Slide 13 text

2. RxJava

Slide 14

Slide 14 text

RXJAVA

Slide 15

Slide 15 text

fun onPurchaseClicked(view: View) { Observable.just(isNotLoggedIn()) .flatMap { if (it) { RxActivityResult.on(this) .startIntent(LoginActivity.newIntent(this)) .map { it.resultCode() == Activity.RESULT_OK } } else { Observable.just(true) } } .filter { it } .subscribe { doPurchase(itemId) } ‌} RXJAVA

Slide 16

Slide 16 text

RXJAVA ‣ Seems more fluent ‣ But what if the process is killed when it’s in background?

Slide 17

Slide 17 text

RXJAVA ‣ Application instance holds the Subject ‣ The Subject is not restored when the process is restored → it must not work and doesn’t

Slide 18

Slide 18 text

KOTLIN COROUTINE ⚠ It’s just an idea and I’m not sure if it works

Slide 19

Slide 19 text

fun onPurchaseClicked(view: View) { launch(UI) { if (isNotLoggedIn()) { val intent = … val (resultCode, _) = startIntent(intent) if (resultCode != Activity.RESULT_OK) { return@launch } } doPurchase(itemId) } } private suspend fun startIntent(intent: Intent): Result { } KOTLIN COROUTINE Execution can be
 suspended here Can be resumed
 from here?

Slide 20

Slide 20 text

KOTLIN COROUTINE https://github.com/Kotlin/kotlin-coroutines/blob/master/kotlin-coroutines-informal.md

Slide 21

Slide 21 text

KOTLIN COROUTINE

Slide 22

Slide 22 text

KOTLIN COROUTINE https://github.com/Kotlin/kotlin-coroutines/issues/28

Slide 23

Slide 23 text

WRAP UP ‣ There are some approaches to make starting an Activity and receiving the result more easy ‣ Annotation Processor ‣ RxJava ‣ Kotlin Coroutine ‣ But none seems perfect yet!

Slide 24

Slide 24 text

Thank you! Hiroshi Kurokawa (ࠇ઒ ༸) @hydrakecat https://github.com/hkurokawa https://speakerdeck.com/hkurokawa hydrakecat.hatenablog.jp