2013/10/08 このエントリーをはてなブックマークに追加 はてなブックマーク - 【Android】Activityスタックを削除する

【Android】Activityスタックを削除する

Activityスタック

今回はスタック(アプリの画面履歴)の一括削除を行いたい場合の実装を紹介したいと思います。




 まずは仕組みについて




Activityは遷移するごとにスタックされていきます。
スタックされた情報はActivityManagerが保有しているようです。



※スタックされる仕組みについては、yanzmさんが、詳しく書いていらっしゃるので、そちらを参考にしてください。
Y.A.M の 雑記帳 -Android Activity, Task, Stack, Launch mode




Activityをスタックから削除する方法は

1.Activityのfinish()メソッドを使うか、
2.Intentのフラグ(FLAG_ACTIVITY_CLEAR_TOPなど)を利用する

方法の2パターンがあると思います。
画面遷移する際に、上記の手法を取らない場合、どんどんスタックにActivityが積み重なっていくというわけです。

※Intentフラグについてはhyoromoさんが一覧化されています。
hyoromoの日記 -IntentのCategoryとExtraとFlagの一覧表を作ってみたよ



例えば、A→B→C画面に遷移した場合、
スタックは



A
B
C



このように積み重なっていきます。



A→Bでfinishメソッドを使用してから、遷移→C画面に遷移した場合、
スタックは



A
C



このように積み重なっていきます。



積み重なったスタックはバックキーを押す時に順番に呼び出されます。


つまり、

各Activityの遷移のタイミングでスタックに残すかどうかの処理を仕込まなければいけないのです。





 部分的に画面履歴を残したいときは??





しかし、C画面でアプリを終了し、アプリ再開時には一番はじめからスタート(つまり、スタックを全て消したい)したいなんてこともあるはずです。
毎回スタックに残らないように処理を施せば良いのですが、検索履歴を残したいなど、要件的にそうもいかないという状況の場合。


こういった時に、なんとかスタックに残っているActivityを操作してスタック上から削除してしまえないかと調べてみましたが、なかなか難しい。


startActivityForResultを使用して遷移したActivityに関しては、
finishActivityメソッドを利用してスタックから削除出来るなんて話もありますが、
上手くいかないという人もいたり。


また、Androidmanifest.xmlで静的にActivityに対してスタックに残すかどうかの設定が出来るようです。

ただ、この場合だと、もちろん動的な設定は出来ないし、
融通が聞かない感じがしますね。




 今回考えてみた実装



ということで、今回簡単な実装を作りました。
疑似スタックを作るイメージです。あんまり綺麗ではないですが。








public class ActivityStack {

    private static <Activity> stackList = new ArrayList<Activity>();

    /**
     * コンストラクタ
     */
    private ActivityStack() {
    }

    public static void removeHistory() {
        for (Activity stack : stackList) {
            stack.finish();
        }
        stackList = new ArrayList<Activity>();
    }

    public static void stackHistory(Activity stack) {
        stackList.add(stack);
    }

}




擬似的にアンドロイドのフレームワークで行っているアクティビティのスタックを再現してしまおうという
なかなか、邪道なやり方です(笑)


staticなリストにアクティビティのインスタンスを詰めておきます。
そして、予期タイミングでスタックを解放すべく、すべてのアクティビティをfinishで解放します。


これにより、今まで各アクティビティでIntentのフラグの処理や、自分自身のfinishメソッドを呼び出さなければ行けなかった手間が省ける訳です。
これを拡張して、何番目のアクティビティだけ消すとかといった事も出来ます(あんまり需要はないと思いますが)。
使いやすさの問題ですが、別にstaticなフィールドはマップとかでも良いと思います。
ただ、マップだとスタックしてる感がないなーってのと、拡張for分の方が扱いやすいなあという、個人的な思いがあり、Listにしてます。



実際使うと、こんな感じですかね。




public class HogeActivity extends Activity implements
        OnItemClickListener, OnItemLongClickListener {

    @Override
    public void onItemClick(AdapterView<?> arg0, View arg1, int arg2, long arg3) {

                    // 遷移処理
                    Intent intent = new Intent(this , Next.class);
                    startActivity(intent);
                    // 疑似スタックに詰める  
         ActivityStack.stackHistory(this);
    }


        /**
          * アプリ終了メソッド
          *
          */
     private void finishApplication(){
                   // アクティビティスタックの削除
                   ActivityStack.removeHistory();
                   // 端末のホーム画面に戻る
                   moveTaskToBack(true);
                   finish();
        }




あったらちょっと便利かなと思い、今回、紹介させていただきました!
以上です。








1 件のコメント:

  1. private static stackList = new ArrayList();
    が動かないような~

    返信削除