onactivityresult -...
TRANSCRIPT
OnActivityResult
kyobashi.dex #4
おまえら!もうonActivityResultでswitchとif書く時代は終わりだぞ!
About Me
Shinobu Okano
@operandoOS
Mercari, Inc.
Souzoh, Inc.
Do you know onActivityResult?
Do you know onActivityResult?
https://developer.android.com/training/basics/intents/result.html
Getting a Result from an Activity
Getting a Result from an Activity
// Start the Activitystatic final int PICK_CONTACT_REQUEST = 1; // The request code
private void pickContact() { Intent pickContactIntent = new Intent(Intent.ACTION_PICK, Uri.parse("content://contacts")); pickContactIntent.setType(Phone.CONTENT_TYPE); // Show user only contacts w/ phone numbers startActivityForResult(pickContactIntent, PICK_CONTACT_REQUEST);}
// Receive the Result@Overrideprotected void onActivityResult(int requestCode, int resultCode, Intent data) { if (requestCode == PICK_CONTACT_REQUEST) { if (resultCode == RESULT_OK) { // ... } }}
某フリマアプリから拝借した
onActivityResult
※定数名とかそこら辺は変えてます
某フリマアプリ onActivityResult
@Overrideprotected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); switch(requestCode) { case LOGIN: if(resultCode == RESULT_OK) { success(); } else { failed(); } break; }}
@Overrideprotected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if(resultCode != RESULT_OK) return; switch (requestCode) { case REQUEST_MUGAMUGA: successItemPost(); break; }}
某フリマアプリ onActivityResult
@Override public void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if (resultCode != RESULT_OK || data == null) { mugemuge(); return; } if (requestCode == Request.UMUUMU) { umuumu(); } }
某フリマアプリ onActivityResult
@Overridepublic void onActivityResult(int requestCode, int resultCode, Intent data) { if (resultCode == Activity.RESULT_CANCELED) { cancel(); } else if (requestCode == REQUEST_CODE_SELECT_IMAGE) { // .... } else if (requestCode == REQUEST_CODE_TRIMMING) { // .... } else { super.onActivityResult(requestCode, resultCode, data); }}
某フリマアプリ onActivityResult
@Overrideprotected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if (requestCode == REQUEST_MUGAMUGA && resultCode == Activity.RESULT_OK) { if (data != null) { mugamuga(); } }}
某フリマアプリ onActivityResult
@Overridepublic void onActivityResult(int requestCode, int resultCode, Intent data) { if (resultCode != Activity.RESULT_OK) { return; } switch (requestCode) { case REQUEST_CODE_CATEGORY: // ... break; case REQUEST_CODE_LOCATION: // ... break; case REQUEST_CODE_CONDITION: // ... break; default: super.onActivityResult(requestCode, resultCode, data); break; }}
某フリマアプリ onActivityResult
onActivityResultの悪さ
• switchとifが多い
• requestCodeとresultCodeをチェックしないといけない
• switchとifの書き方がまちまち
• switch使わない勢 + if else勢😇
• requestCodeとresultCodeどっちに先に判定するか問題
• 人間が書くにはつらい...
Do you know OnActivityResult?
OnActivityResult
OnActivityResult annotation compiler for Android
https://github.com/vanniktech/OnActivityResult
アッテの
onActivityResultの実装は
すべてOnActivityResultです!
onActivityResultの実装がこれだけ!!
@Overrideprotected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); ActivityResult.onResult(requestCode, resultCode, data).into(this);}
すぎょい😆
受け取ったあとの実装は??
• それぞのたパターンにあったメソッドを定義して@OnActivityResultをつける
• @OnActivityResultのrequestCodeとresultCodesでどういう結果の場合に呼び出してほしいかを定義する
受け取ったあとの実装は??
@OnActivityResult(requestCode = REQUEST_TAKE_PHOTO, resultCodes = RESULT_OK)void onTakePhoto(@ExtraString(name = CameraActivity.RESULT_TAKE_PHOTO) final String takePhoto) { Intent resultIntent = new Intent(); resultIntent.putExtra(RESULT_TAKE_PHOTO, takePhoto); setResult(RESULT_CODE_TAKE_PHOTO, resultIntent); finish();}
受け取ったあとの実装は??
// result codeに何が返ってきても処理するメソッド@OnActivityResult(requestCode = REQUEST_SELECT_IMAGE)void onHumuHumu() { Toast.makeText(this, "onHumuHumu", Toast.LENGTH_SHORT).show();}
@OnActivityResult(requestCode = REQUEST_SELECT_IMAGE, resultCodes = RESULT_CANCELED)void onCancel() { Toast.makeText(this, "cancel select image.”, Toast.LENGTH_SHORT).show();}
すぎょくない?
(みんな)
すぎょい😍
onActivityResultの受け取り先のオブジェクトを指定する• intoに受け取り先オブジェクトを指定する
• ActivityResult.onResult().into(obj);
• onActivityResultで返ってくるIntentのデータをViewModelとかPresenterで受け取る
• 設計によっては嬉しい
onActivityResultの結果をViewModelで受け取る
private MySampleMainViewModel viewModel = new MySampleMainViewModel();
@Overrideprotected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); ActivityResult.onResult(requestCode, resultCode, data).into(viewModel);}
public class MySampleMainViewModel {
public ObservableField<String> location = new ObservableField<>("0,0");
@OnActivityResult(requestCode = MySampleMainActivity.REQUEST_SELECT_LOCATION, resultCodes = Activity.RESULT_OK) void onSelectedLocation(@Extra(name = LocationSelectActivity.RESULT_SELECT_LOCATION) Location location) { this.location.set(location.toString()); }}
OnActivityResult sample Code
https://github.com/operando/OnActivityResult/tree/my_sample_code/onactivityresult-sample
https://github.com/operando/OnActivityResult/tree/my_sample_code/onactivityresult-sample/build/generated/source/apt/debug/com/vanniktech/onactivityresult/sample
布教活動のために適当にサンプルコード書いてます
annotation processorで作成されるコードも
入れてあります
Do you know Activity.RESULT_FIRST_USER?
• Start of user-defined activity results.
• Constant Value: 1 (0x00000001)
• https://developer.android.com/reference/android/app/Activity.html#RESULT_FIRST_USER
どういう場合に使うか
• 画面Aから画面BへRequestをする時画面Bからの戻りが2パターン以上ある場合
• ???
アッテの例)募集投稿画面から画像選択をする
• 画像選択画面ではギャラリーの画像を選択するか、カメラで撮影するかの 2パターンある
• カメラ撮影はまた別画面が起動して、その戻りを画像選択画面が受け取る
• 募集投稿画面への戻りが、ギャラリーの画像を選択、カメラで撮影の2パターンある
• = 募集投稿画面から画像選択画面に対しては1Requestだけど 2パターンの戻り(Resultパターン)がある
• = 独自のResult Codeを定義したい = Activity.RESULT_FIRST_USERを使って定義
アッテの例で...
アッテの例で...
OnActivityResultで実装すると…
// ImageSelectActivitystatic final int RESULT_CODE_SELECT_IMAGE = Activity.RESULT_FIRST_USER;static final int RESULT_CODE_TAKE_PHOTO = Activity.RESULT_FIRST_USER + 1;
@OnActivityResult(requestCode = REQUEST_SELECT_IMAGE, resultCodes = ImageSelectActivity.RESULT_CODE_SELECT_IMAGE)void onSelectImage(Intent intent) { ArrayList<String> selectImages = intent.getStringArrayListExtra(RESULT_SELECT_IMAGES); Toast.makeText(this, "onSelectImage selectImages : " + selectImages, Toast.LENGTH_SHORT).show();}
@OnActivityResult(requestCode = REQUEST_SELECT_IMAGE, resultCodes = ImageSelectActivity.RESULT_CODE_TAKE_PHOTO)void onTakePhoto(@ExtraString(name = ImageSelectActivity.RESULT_TAKE_PHOTO) final String takePhoto) { Toast.makeText(this, "onTakePhoto takePhoto : " + takePhoto, Toast.LENGTH_SHORT).show();}
Support user defined result code
https://github.com/vanniktech/OnActivityResult/pull/86
俺が!
OnActivityResultでActivity.RESULT_FIRST_USER
使えるようにしてやったぞ!
Contributions
Contributions
Contributions
イヤッッホォォォオオォオウ!
OnActivityResultの気に入ってるところ
• onActivityResultメソッドの実装はシンプルになる!
• startActivityForResultの呼び出しは既存のままでいい!
• 受け取り後の処理ごとにメソッド定義するので見通しがいい
• 結果受け取り先のオブジェクトを指定できる → into()
• ifとswitchからの開放…
おまえら! もうonActivityResultで
switchとif書く時代は終わりだぞ!
Thanks!!