Activityが別のActivityを呼び出す
(startActivityForResultがdeprecatedになったので対応)
androidx java

2023.10.5 2020.6.1 Coskx Lab  

1 はじめに

MainActivityから別のアクティビティ(例えばSubActivity)を起動して,なにか作業をして再びMainActivityに復帰することを考えます。
また,起動・復帰時に値(複数)をやり取りすることも考えます。
その時,各アクティビティのライフサイクルがどうなっているのかも,追ってみることにします。

  ソースコードのダウンロード


2 使用環境

3 テストアプリ

テストアプリを次のように作ります。
MainActivityには2つボタンがあり,それぞれSubActivityかSub2Activityを起動します。
SubActivityを起動するときは,値を1つ送ります。SubActivityからMainActivityに戻る際は,受け取った値を1増やしてMainActivityに持ち帰ります。
Sub2Activityを起動した場合は,何もせずMainActivityに戻ってきます。
アプリ内には3つのActivityを作るので,AndroidManifest.xmlに3つののActivity(「.MainActivity」「.SubActivity」「.Sub2Activity」)を登録しておきます。


4 値の受け渡しを伴わないときのアクティビティ間の移動

「MainActivity」で,移動要求のボタンが押されたら別のアクティビティ「Sub2Activity」を立ち上げで移動することにします。
また,帰りは「Sub2Activity」で,戻り要求のボタンが押されたら,自分のアクティビティ「Sub2Activity」を閉じて,「MainActivity」に復帰するようにします。
それぞれのところは次のようなコードになります。

4.1 MainActivityでの記述(「MainActivity」から「Sub2Activity」を起動する)

ボタンのリスナとして記述されています。
Sub2ActivityのIntentを作成して,それを起動しています。

    Intent varIntent2 = new Intent(getApplicationContext(),Sub2Activity.class);
    startActivity(varIntent2);

4.2 Sub2Activityでの記述(「Sub2Activity」から「MainActivity」に戻る)

ボタンのリスナとして記述されています。
単にSub2Activityを終了するだけです。そうするとMainActivityが再起動します。

    finish();


5 値の受け渡しを伴うときのアクティビティ間の移動

「MainActivity」で,移動要求のボタンが押されたら別のアクティビティ「SubActivity」を立ち上げで移動することにします。
SubActivityを起動するときは,値を1つ送ります。
また,帰りは「SubActivity」で,戻り要求のボタンが押されたら,自分のアクティビティ「SubActivity」を閉じて,「MainActivity」に復帰するようにします。
SubActivityからMainActivityに戻る際は,受け取った値を1増やしてMainActivityに持ち帰ります。

送る値と戻す値を設定する際に次のような合言葉を使います。(合言葉の文字列は何でもOKです)
この合言葉はMainActivity.java内に記述されますが,他からも参照できるようにpublicになっています。
    public static final String DATA_TO_SUB = "DATA_TO_SUB";  //mainからsubに値を送るときの合言葉
    public static final String DATA_TO_MAIN = "DATA_TO_MAIN";  //subからmainに値を送るときの合言葉

それぞれの作業は次のようなコードになります。

5.1 MainActivityでの記述(値を伴って「MainActivity」から「SubActivity」へ移動)

「MainActivity」で,移動要求のボタンが押されたら別のアクティビティ「SubActivity」に移動することにします。
このとき,int型の値を1つ持ってゆくことにします。
onCreate内で,予めIntentとlancharを作成し,lanchar内(result ->)に,戻ってきたときにすることを記述しておきます。
戻ってきた値は合言葉DATA_TO_MAINを確かめながらresult.getData().getIntExtraで受け取ります。
受け取った値はToastにて表示した後,画面へ表示します。
「MainActivity」から「SubActivity」への移動は,ボタンのリスナに記述します。 varIntent1.putExtraで,合言葉DATA_TO_SUBを付けて,値(画面に表示されている値)をセットしてから,launcherで「SubActivity」を起動します。 「SubActivity」は起動直後に,onCreate()にて,合言葉を確かめて,値を取得します。
(ここでの合言葉は DATA_TO_SUB)

MainActivityのonCreateで作業準備
MainActivityに次の2つの変数を作っておいてから
    private Intent varIntent1;
    private ActivityResultLauncher<Intent> launcher;
についてonCreateで次のように記述します。

    // アクティビティ1を作る
    varIntent1 = new Intent(getApplication(), SubActivity.class);
    launcher= registerForActivityResult(
            new ActivityResultContracts.StartActivityForResult(),
            result -> {
                Log.i(TAG,"result");
                if (result.getResultCode() == Activity.RESULT_OK) {
                    assert result.getData() != null;
                    int res = result.getData().getIntExtra(MainActivity.DATA_TO_MAIN, 0);
                    Toast.makeText(MainActivity.this , "returned with "+res, Toast.LENGTH_LONG).show();
                    value = res;
                }
            });

「MainActivity」のボタンのリスナではint型変数valueの値を送り,SubActivityを起動

    //call
    varIntent1.putExtra(MainActivity.DATA_TO_SUB, value);
    launcher.launch(varIntent1);

5.2 SubActivityでの記述(「SubActivity」から「MainActivity」に値を伴って戻る)

「SubActivity」が起動したら,onCreateで,intentに自分を起動したインテントを保存し,合言葉DATA_TO_SUBを確認しながらintent.getIntExtraで,値を受け取る。 「SubActivity」で,戻り要求のボタンが押されたら,自分のアクティビティを閉じて,「MainActivity」に復帰するようにします。
このとき,int型の値を1つ持って帰ることにします。(このアプリではもらった値を1増やして返すことにします)
合言葉 DATA_TO_MAINを使い,intent.putExtraで持って帰る値をインテントに設定します。

SubActivityのonCreateで値を受け取る

    intent = getIntent();
    value = intent.getIntExtra(MainActivity.DATA_TO_SUB, 0);  //合言葉はDATA_TO_SUB

SubActivityのボタンリスナにint型変数valueの値を送り,SubActivityを終了することを記述する

    //MainActivityにvalueを持って帰る
    int returnvalue = value + 1; // 1増やして返すことにする
    intent.putExtra(MainActivity.DATA_TO_MAIN, returnvalue);     //合言葉はMainActivityで定義されているDATA_TO_MAIN
    setResult(RESULT_OK, intent); //RESULT_OK または RESULT_CANCELED を返す
    // 自アクティビティを閉じ、もとのアクティビティに戻る
    finish();

5 各アクティビティのライフサイクル

各アクティビティのライフサイクルを,onXXXメソッドの先頭のところでログ表示をして追跡しました。

MainActivityの起動(通常通り)
onCreate → onStart → onResume
と進みます。
MainActivityでSubActivityへの移動要求のボタンクリック
MainActivityでは
onPause → onStop
と進みます。MainActivityはonDestroyまでは進みません。
SubActivityでは,
onCreate → onStart → onResume
と進みます。
SubActivityでMainActivityへの戻る要求のボタンクリック
SubActivityでは
onPause → onStop → onDestroy
まで進み,完全に終了しています。
同時にMainActivityでは
onRestart → onStart → onResume
と復帰するのですが,SubActivityが単に「finish();」だけではなく,「setResult();finish();」で復帰する場合は,
onRestart → onStart → result → onResume
のようになっています。


補足 複数のアクティビティがある中で,MainActivityがアプリ起動時のアクティビティになるのは,AndroidManifest.xmlでintent-filterで設定されているからです。

6 まとめ

MainActivityが別のアクティビティを起動して,復帰する方法を示しました。
MainActivityが別のアクティビティを起動するさい,値を持ってゆく方法,復帰時には戻り値を受け取る方法を示しました。
動作の流れを追跡して,MainActivityではonDestroyまでは進まないこと,MainActivityが復帰時に値を受け取る際は,onResumeより前にresultで受け取ることが判りました。