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"にする
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.sample.test.myapplication"> <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/Theme.MyApplication"> <activity android:name=".MainActivity3" android:exported="true" android:launchMode="singleInstance" />★コレ! <activity android:name=".MainActivity2" android:exported="true" android:launchMode="singleInstance" />★コレ! <activity android:name=".MainActivity" android:exported="true" android:launchMode="singleInstance">★コレ! <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> </manifest>
別アプリへ一時遷移する場合を考慮すると問題ありますけどね。。。(^_^;
0 件のコメント:
コメントを投稿