布団の中にいたい

Androidアプリ開発の勉強をしている傍らで、elasticsearchとかをいじってみたりしています。最近は数学の勉強が楽しくなってきました。

onBackPressedの落とし穴

onKeyDownをonBackPressedに切り替えて使ってみたら、問答無用で遷移前のActivityに戻されてしまう現象に遭遇しました。正直中途半端な知識で使うのはどうかと思っていたので、内部でどのような動作をしているか少し調べてみました。

ソースコードをどんどん辿っていったところ、onBackPressedが定義されているのは、Activity.javaの内部です。同様にonKeyDownもActivity.javaにありました。

実装されていたonBackPressedは以下です。

コメントを見るだけで何やら不穏な空気が漂っていますね。とりあえず簡単な実装として、何かするためにonBackPressedをoverrideできるときは現在のActivityを終了しますとのこと。

    /**
     * Called when the activity has detected the user's press of the back
     * key.  The default implementation simply finishes the current activity,
     * but you can override this to do whatever you want.
     */
    public void onBackPressed() {
        if (mActionBar != null && mActionBar.collapseActionView()) {
            return;
        }

        if (!mFragments.getFragmentManager().popBackStackImmediate()) {
            finishAfterTransition();
        }
    }

終了処理は、finishAfterTransitionっぽいですね。Fragmentのスタックから何も取り出せないとき(addToBackStackとかしてない)にこの処理に入ります。次にfinishAfterTransitionを見てみます。

ActivityTransitionStateはActivityの遷移状況を管理しているんですかね。ソース眺めてみましたが、他のものと違って色々知識が必要なので、メソッド名の字面から判断します。

    /**
     * Reverses the Activity Scene entry Transition and triggers the calling Activity
     * to reverse its exit Transition. When the exit Transition completes,
     * {@link #finish()} is called. If no entry Transition was used, finish() is called
     * immediately and the Activity exit Transition is run.
     * @see android.app.ActivityOptions#makeSceneTransitionAnimation(Activity, android.util.Pair[])
     */
    public void finishAfterTransition() {
        if (!mActivityTransitionState.startExitBackTransition(this)) {
            finish();
        }
    }

すべてを理解しきれたわけではありませんが、onBackPressedの行き着く先にはfinishがいることがわかりました。ちらっとonKeyDownも眺めてみましたが、実のところ、内部でonBackPressedを呼んでいたので使う際は注意が必要かもしれません。

PS Android Studioのどんどんメソッドを辿っていける機能、ソース読むときにかなり便利だということに気づきました。