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

Making onActivityResult More Easy

Making onActivityResult More Easy

2018-02-06 shibuya.apk #22

In this talk, I am talking about onActivityResult in Android development, starting an Activity and receiving the result. I am introducing some approaches and some hints to make it more easy.

Hiroshi Kurokawa

February 06, 2018
Tweet

More Decks by Hiroshi Kurokawa

Other Decks in Technology

Transcript

  1. 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?
  2. 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
  3. 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
  4. ANNOTATION PROCESSOR override fun onActivityResult( requestCode: Int, resultCode: Int, data:

    Intent? ) { super.onActivityResult(requestCode, resultCode, data) ActivityResult .onResult(requestCode, resultCode, data) .into(this) }
  5. ANNOTATION PROCESSOR @OnActivityResult(requestCode = REQ_CODE_LOGIN) fun handleLoginResult(resultCode: Int) { …

    } @OnActivityResult(requestCode = REQ_CODE_PURCHASE) fun handlePurchaseResult(resultCode: Int, data: Intent?) { … }
  6. ANNOTATION PROCESSOR ‣ Simple ‣ Less boilerplate code ‣ But

    there is still a distance between startActivity and onActivityResult
  7. 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
  8. YOU HAVE TO ‣ Remember the last context ‣ Resume

    the process when user backs to the screen ‣ Handle all the possible cases Not that easy
  9. 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
  10. RXJAVA ‣ Seems more fluent ‣ But what if the

    process is killed when it’s in background?
  11. RXJAVA ‣ Application instance holds the Subject ‣ The Subject

    is not restored when the process is restored → it must not work and doesn’t
  12. 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?
  13. 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!