Androidで次のことが必要な場合……
- 別Activityから戻ってきたら何かしたい、
- ファイルを選択させた後に処理したい、
- 共有アクション後に何か後処理したい
こういうのは onActivityResult を使ってました。
でもいつからか非推奨扱いになったようです。
代替方法は ActivityResultLauncher への置き換え
この置換方法・コード例を改めてまとめたいと思います。
このページの目次
従来はこんな風にonActivityResult()を使ってた
まずは従来までの方法について(非推奨)
例えば別Activityに遷移するとします。
そのあと元Activityに帰ってきたら何かしたいです。
▼ 別ActivityをIntentから開く(Java)
1 2 3 |
Context context = MainActivity.this; Intent intent = new Intent(context, NextActivity.class); startActivityForResult(intent, 12345); |
普通に別Activityを開くだけではなく、
元Activity遷移度に何か処理したいことがあります。
▼ そこでonActivityResult()をオーバライド
1 2 3 4 5 6 7 8 9 |
@Override public void onActivityResult(int requestCode, int resultCode, Intent intent) { super.onActivityResult(requestCode, resultCode, intent); if(requestCode == 12345) /// 元Activity遷移後の処理 } } |
これが非推奨となります(詳細は後述)
厄介なのは Activity#onActivityResult() が今までポピュラーな方法であり、それを非推奨と言われると「このまま使ってて大丈夫?」と不安になることです。
しかも多方面でonActivityResult()は使われている
別Activity遷移の結果を受け取るだけじゃありません。
本当に多方面でonActivityResult()は使われてます。
例えば今までの使用例を挙げるなら……
▼ Android10以降のファイル保存の正しいやり方
▼ Intentからウェブページを開く方法・コード例
▼ Androidで簡単にシェア機能を実装する
エクスプローラーを起動してファイル選択した結果(Uri)を受け取ったり、Intentからウェブページ・シェアした結果を受け取ったり……あらゆる場面で使われてます。
特にファイル選択とかは使う場面が多いですよね。
ただしonActivityResult()は全面的に非推奨ではない
ここまで非推奨と書いてきました。
でもonActivityResultが全面的に非推奨ではないです。
▼ 公式リファレンスでも補足されている
基盤となる startActivityForResult() API と onActivityResult() API はあらゆる API レベルの Activity クラスで使用できますが、AndroidX Activity と Fragment で導入された Activity Result API を使用することを強くおすすめします。
引用元 : https://developer.android.com/training/basics/intents/result
「あらゆる API レベルの Activity クラスで使用できます」
つまり従来のActivityなら問題なく使用できるってこと
また普通のActivity#onActivityResultは非推奨ではないです。
ただ強くおすすめしてることは変わりありません。
正確にはAndroidX Activityなどで非推奨になっただけ
この非推奨問題は正しく理解されるべきです。
正確には次のクラスで非推奨という話になります。
- ComponentActivity#onActivityResult
- FragmentActivity#onActivityResult
確かにこれらActivityクラスでは非推奨です。
でも普通のActivityクラスでは非推奨ではありません。
詳しくはActivity#onActivityResultとか見てください。
間違っても全部のActivityクラスで非推奨ではありません。
代替方法はActivityResultLauncherに置き換えるだけ
とはいえonActivityResult()はあまり推奨されません。
今まで「強く推奨」から「少し推奨」に弱くなった感じ
だから ActivityResultLauncher で置き替えます。
例えば別Activity遷移後に結果を受け取りたい場合、
次のような手順を踏めば置き換えすることも可能です。
1.registerForActivityResultから結果コールバック登録
▼ 次のActivityResultLauncherを定義(kotlin)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
private lateinit var testLauncher: ActivityResultLauncher<Intent> override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) testLauncher = registerForActivityResult( ActivityResultContracts.StartActivityForResult() ){ result -> /// 元Activityに帰ってきた時の処理 /// ... /// リザルトコード・Intentも取得可能 val resultCode: Int = result.resultCode val data: Intent? = result.data } } |
上記のように registerForActivityResult() からコールバックを登録し、Activityの結果(応答コード・URI・etc)を受け取ることが可能です。
あと result はActivityResult型です。
▼ 従来の結果を受け取るのに使える
- ActivityResult.resultCode
今までの onActivityResult() における resultCode と同じ値。この値が Activity.RESULT_OK と等しいなら遷移先の処理が成功したことを表す
- ActivityResult.data
遷移元から帰ってきたIntentデータ。例えばファイル選択後にファイルURIを受け取りたいなら result.data?.data から参照することができる
結果コード・Intentを受け取れるのは変わりません。
2.IntentをActivityResultLauncherから起動する
そしたら目的のActivityを起動します。
▼ 例えば次のようなコード例
1 2 3 |
val context = MainActivity@this val intent = Intent(this, NextActivity::class.java) testLauncher.launch(intent) |
このコードみたいに startActivityForResult() であったものを、 testLauncher.launch(chooser) みたいに置き返してやればOKです。あとは特筆すべきこともありません。
以上、onActivityresultが非推奨になった話でした。
可能なら ActivityResultLauncher を使うのがベストです。