Android savedInstanceStateはどのタイミングで値が入るのか

2019年8月29日

Androidのサンプルを眺めてると
Fragmentを作るときのActiityで、以下のような作りになっているのを見かける

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main_activity);

        if (null == savedInstanceState) {
            SampleFragment fragment = new SampleFragment();

            getSupportFragmentManager().beginTransaction()
                    .add(R.id.main_container, fragment)
                    .commit();
        }
    }
}

8行目の「savedInstanceState」にはいつ値が入るのか
Activity破棄の話と一緒に調べていきたい。

 

初回起動

結果
savedInstanceState = null

初回起動や、画面遷移などでActivityが初めて生成された場合は
savedInstanceStateはnullになる。

 

画面回転

結果
savedInstanceState = {Bundle@4849}

画面回転した場合は何かしら値が入ってくる。
回転した時はActivityが破棄されてonCreate()が呼ばれるが
状態を復元するための値が入ってくる。

Emulatorで回転したときに入ってきた値をみてみる。

Bundle[
    {android:viewHierarchyState=Bundle[
        {android:views={
            16908290=android.view.AbsSavedState$1@6d79b40,
            2131165191=androidx.appcompat.widget.Toolbar$SavedState@e9aca79,
            2131165193=android.view.AbsSavedState$1@6d79b40,
            2131165199=android.view.AbsSavedState$1@6d79b40,
            2131165234=android.view.AbsSavedState$1@6d79b40,
            2131165265=android.view.AbsSavedState$1@6d79b40
            }
        }
    ],
    android:support:fragments=androidx.fragment.app.FragmentManagerState@42f43be,
    android:fragments=android.app.FragmentManagerState@1b7ec1f
    }
]

ActivityとFragmentだけの簡単な構成の場合
複数のViewとfragmentが入るのね。

Bundleにputするような処理は一つも入れてないけど
復元するために必要な情報が自動で入ってくるみたい。

EditTextに文字が入っていて、回転後も文字が入ってるのは
この復元が一役買っているのだろう。

 

Homeボタン押下後起動

結果
呼ばれない

そもそもonCreate()が呼ばれない

 

Overviewボタン押下後起動

結果
呼ばれない

こちらも、そもそもonCreate()が呼ばれない

 

Overviewボタン押下→タスクkill後起動

結果
savedInstanceState = null

Activityを一から作り直しなので、初回起動と同じ挙動

 

メモリ不足

結果
savedInstanceState = {Bundle@4859}

アプリがバックグラウンドにいる状態で
メモリが逼迫してActivityが破棄された場合は
Activityが再起動して復元される。

メモリ不足を再現するのは大変なので
設定の開発者オプションにある、以下の設定にチェックを入れる。

アクティビティを保持しない
(Don’t keep activities)

チェックを入れた状態で
Homeボタン押下からの起動や、Overviewボタン押下から起動することで
メモリ不足によるActivityの破棄を疑似的に再現することができる。

実機でリアルにメモリ不足状態にしたいなら
「Fill RAM memory」
というメモリ不足に追い込むアプリもある。

 

設定変更

結果
savedInstanceState = {Bundle@4860}

言語や画面サイズの設定変更などでもActivityが破棄され
再表示時は復元のためsavedInstanceStateに値が入ってくる。

全ての設定変更を試したわけではないので
興味があればDeveloperのDocsを参考にすると良い。
https://developer.android.com/guide/topics/manifest/activity-element.html?hl=ja#config

 

まとめ

Activityが破棄される条件に当てはまると
復元のためにsavedInstanceStateに値が入ることが分かる。

今回確認がとれたActivityが破棄される条件
・画面回転
・メモリ不足
・設定変更

開発日記

Posted by konp