メソッドonSaveInstanceState()
およびonRestoreInstanceState()
を使用して、Activity
の状態を保存および復元しようとしています。
問題は、onRestoreInstanceState()
メソッドに決して入らないことです。誰がこれがなぜなのか説明できますか?
通常、onCreate()
で状態を復元します。 onRestoreInstanceState()
でも復元できますが、あまり一般的ではありません。 (onRestoreInstanceState()
はonStart()
の後に呼び出されますが、onCreate()
はonStart()
の前に呼び出されます。
Putメソッドを使用して、値をonSaveInstanceState()
に保存します。
protected void onSaveInstanceState(Bundle icicle) {
super.onSaveInstanceState(icicle);
icicle.putLong("param", value);
}
そして、onCreate()
の値を復元します。
public void onCreate(Bundle icicle) {
if (icicle != null){
value = icicle.getLong("param");
}
}
ビューステートは保存されるため、保存する必要はありません 自動的に super.onSaveInstanceState(icicle);を呼び出します。
onRestoreInstanceState()
が呼び出されます再作成時のみ OSによるkilledの後のアクティビティ。このような状況は次の場合に発生します。
onRestoreInstanceState()
が呼び出されます。対照的に、アクティビティ中にデバイスのBack
ボタンを押すと、アクティビティはfinish()ed(つまり、デスクトップアプリケーションの終了と考えられます)になり、次回アプリを起動すると「新鮮」に開始されます。 Back
をヒットしたときに意図的に終了したため、保存された状態はありません。
他の混乱の原因は、アプリが別のアプリにフォーカスを失ったときにonSaveInstanceState()
が呼び出されるが、アプリに戻るときにonRestoreInstanceState()
が呼び出されない場合があることです。これは、元の質問で説明した場合です。つまり、他のアクティビティが前面にあった間にアクティビティが強制終了されなかった場合、アクティビティはほとんど「生きている」ためonRestoreInstanceState()
は呼び出されません。
全体として、onRestoreInstanceState()
のドキュメントに記載されているとおり:
ほとんどの実装はonCreate(Bundle)を使用して状態を復元しますが、すべての初期化が完了した後、またはデフォルトの実装を使用するかどうかをサブクラスが決定できるようにすると便利です。このメソッドのデフォルト実装は、onSaveInstanceState(Bundle)によって以前にフリーズされたビューステートの復元を実行します。
私が読んだように:Activity
をサブクラス化していて、誰かがあなたのサブクラスをサブクラス化することが予想されない限り、onRestoreInstanceState()
をオーバーライドする理由はありません。
onSaveInstanceState()
で保存した状態は、後でonCreate()
メソッドの呼び出しで利用できます。したがって、onCreate
(およびそのBundle
パラメーター)を使用して、アクティビティの状態を復元します。
回避策として、アクティビティAを開始するために使用するインテントに、維持するデータを含むバンドルを保存できます。
Intent intent = new Intent(this, ActivityA.class);
intent.putExtra("bundle", theBundledData);
startActivity(intent);
アクティビティAはこれをアクティビティBに返す必要があります。アクティビティBのonCreateメソッドでインテントを取得します。
Intent intent = getIntent();
Bundle intentBundle;
if (intent != null)
intentBundle = intent.getBundleExtra("bundle");
// Do something with the data.
もう1つのアイデアは、アクティビティ状態を保存するリポジトリクラスを作成し、各アクティビティがそのクラスを参照するようにすることです(シングルトン構造を使用することも可能です)。
OnSaveInstanceStateは、別のアクティビティが前面に来ると常に呼び出されることがわかりました。 onStopも同様です。
ただし、onRestoreInstanceStateが呼び出されたのは、onCreateおよびonStartも呼び出されたときだけでした。また、onCreateとonStartが常に呼び出されるとは限りませんでした。
そのため、アクティビティがバックグラウンドに移動しても、Androidは常に状態情報を削除するとは限りません。ただし、ライフサイクルメソッドを呼び出して、安全のために状態を保存します。したがって、状態が削除されない場合、Androidはライフサイクルメソッドを呼び出して状態を復元する必要がないため、状態を復元しません。
図2 これについて説明します。
主なことは、onSaveInstanceState()
に格納しないと、onRestoreInstanceState()
が呼び出されないことです。これは、restoreInstanceState()
とonCreate()
の主な違いです。本当に何かを保管してください。おそらくこれがあなたの問題です。
このスレッドはかなり古いと思います。 onSaveInstanceState()
も呼び出される別のケースに言及しますが、それはActivity.moveTaskToBack(boolean nonRootActivity)
を呼び出すときです。
Android:configChanges="orientation|screenSize"
およびonConfigurationChanged(Configuration newConfig)
を使用してアクティビティの方向の変更を処理している場合、onRestoreInstanceState()
は呼び出されません。
OnSaveInstanceStateの後にonRestoreInstanceStateが常に呼び出される必要はありません。
注意:アクティビティが回転するとき(方向が処理されないとき)にonRestoreInstanceStateが常に呼び出されるか、アクティビティを開いてから他のアプリを開いて、アクティビティインスタンスがOSによってメモリからクリアされます。
私はそのようにすることができます(_#Javaではなくc#ですが、それは問題ではありません...):
private int iValue = 1234567890;
function void MyTest()
{
Intent oIntent = new Intent (this, typeof(Camera2Activity));
Bundle oBundle = new Bundle();
oBundle.PutInt("MYVALUE", iValue); //=> 1234567890
oIntent.PutExtras (oBundle);
iRequestCode = 1111;
StartActivityForResult (oIntent, 1111);
}
結果に対するあなたの活動において
private int iValue = 0;
protected override void OnCreate(Bundle bundle)
{
Bundle oBundle = Intent.Extras;
if (oBundle != null)
{
iValue = oBundle.GetInt("MYVALUE", 0);
//=>1234567890
}
}
private void FinishActivity(bool bResult)
{
Intent oIntent = new Intent();
Bundle oBundle = new Bundle();
oBundle.PutInt("MYVALUE", iValue);//=>1234567890
oIntent.PutExtras(oBundle);
if (bResult)
{
SetResult (Result.Ok, oIntent);
}
else
SetResult(Result.Canceled, oIntent);
GC.Collect();
Finish();
}
最後に
protected override void OnActivityResult(int iRequestCode, Android.App.Result oResultCode, Intent oIntent)
{
base.OnActivityResult (iRequestCode, oResultCode, oIntent);
iValue = oIntent.Extras.GetInt("MYVALUE", -1); //=> 1234567890
}
私はこれに偶然遭遇し、ドキュメントに私の答えがあったことに気づいていました:
「この関数がnull状態で呼び出されることはありません。」
私の場合、onRestoreInstanceStateが最初のインスタンス化で呼び出されないのはなぜだろうと思っていました。これは、何も保存しない場合、ビューを再構築するときに呼び出されないことも意味します。
私の場合、デバイスの向きを変更した後にアクティビティが再構築されたときにonRestoreInstanceState
が呼び出されました。 onCreate(Bundle)
が最初に呼び出されましたが、バンドルにはonSaveInstanceState(Bundle)
で設定したキー/値がありませんでした。
その直後、onRestoreInstanceState(Bundle)
が正しいキー/値を持つバンドルで呼び出されました。