2021年8月22日日曜日

Activityの遷移時、すでに生成しているActivityへ遷移する方法

startActivityでActivityを切り替える場合、
デフォルトのままだと、毎回新規でActivityのインスタンスを作ってしまう。
なので、すでに同名Activityが存在していても、新しいActivityがスタック上にできあがる。


Intentで指定したActivityがすでに生成されている場合は、
生成済みActivityに遷移させるにはどうするか。について書いていく。


Activityの管理

アプリ内でActivityを切り替えていくとき、
Activity達はスタックに積み上げられていく仕組みになっている。
これのおかげで、Backキー押下や今の画面でfinish()をCallしたとき、最上位のActivityをスタックから取り除き、一つ前の画面に戻すことができるわけだ。

なので
古いActivityをstartActivityで呼び出したい場合、スタックの順番を入れ替えることができれば問題は解決する。
例えば
ActivityA ⇒ B ⇒ Cの順で画面遷移をした後に、Aを表示したい場合、
以下のスタック切り替えができればよい。


しかし、このスタックの入れ替え機能は
Androidでは提供されていない(スタック管理なのでLIFO。順番入れ替えは不可)
なので、
どうやってスタックをから任意の古いActivityを抜き出すかが焦点となる。


AndroidManifestのLaunchModeを利用

Activityのスタックの挙動は
AndroidManifestのlaunchModeである程度制御できる。
(さすがに、上の理想形の制御はできないのだが....)

上に習い
ActivityA ⇒ B ⇒ Cの順で画面遷移をした後に、Aを表示したい場合を例に
設定毎の挙動を解説する。

launchMode:standard(デフォルト)、singleTop


ActivityAを呼び出しても、新規で作成してスタックに積む動作になる。 
古いActivityAとは関係ないので変数も引き継がれない。
この設定で古いActivityに戻すなら、自信をfinishさせるかBackキー押下させて、 
ActivityBへ移動し、さらにfinishさせる必要がある。ActivityBもCも消えるし制御が難しい。。


launchMode:singleTask


ActivityAがスタックにあれば、その上に積まれているActivityを全て削除してActivityAを表示させる。これなら古いActivityAに戻せる。 
ただ、ActivityBやCは消えるので、この後にB,Cを呼ぶと新規で作られる


launchMode:singleInstance

1つのタスクに1つのActivityとする制御。なのでスタックに積まれない。
バックキー押下すると1つ前のタスクが表示されるから前の画面への遷移もできる。一番理想に近い形。
ただし、HOMEキーでホーム画面へ戻ったり、別のアプリへ切り替えたりすると
フォアグラウンドだったタスク以外全て捨てられるので、その場合は他のActivityは作り直しとなる。


まとめ

Activityで任意の古いActivityへ遷移させたい場合
AndroidManifestでActivityのlaunchMode設定を全て"singleInstance"にする
  1. <?xml version="1.0" encoding="utf-8"?>
  2. <manifest xmlns:android="http://schemas.android.com/apk/res/android"
  3. package="com.sample.test.myapplication">
  4.  
  5. <application
  6. android:allowBackup="true"
  7. android:icon="@mipmap/ic_launcher"
  8. android:label="@string/app_name"
  9. android:roundIcon="@mipmap/ic_launcher_round"
  10. android:supportsRtl="true"
  11. android:theme="@style/Theme.MyApplication">
  12. <activity
  13. android:name=".MainActivity3"
  14. android:exported="true"
  15. android:launchMode="singleInstance" />★コレ!
  16. <activity
  17. android:name=".MainActivity2"
  18. android:exported="true"
  19. android:launchMode="singleInstance" />★コレ!
  20. <activity
  21. android:name=".MainActivity"
  22. android:exported="true"
  23. android:launchMode="singleInstance">★コレ!
  24. <intent-filter>
  25. <action android:name="android.intent.action.MAIN" />
  26.  
  27. <category android:name="android.intent.category.LAUNCHER" />
  28. </intent-filter>
  29. </activity>
  30. </application>
  31.  
  32. </manifest>

これも
別アプリへ一時遷移する場合を考慮すると問題ありますけどね。。。(^_^;

0 件のコメント:

コメントを投稿