Android静的オブジェクトのライフサイクル


101

私はイベント検索アプリケーションを作成しています。ある画面から検索条件を設定し、別の画面に入力してから、ユーザーは3番目の画面から検索条件を編集して4番目の画面に移動します。

上記のタスクを達成するために、アプリケーション周辺の値を記憶する静的オブジェクトを使用しており、特別なことをする必要はありません。

しかし、メモリ不足のアンドロイドが静的オブジェクトを削除した場合、アンドロイドの静的オブジェクトのライフサイクルについて心配ですか?

androidはマルチタスクをサポートしているため、ユーザーが別のアプリケーションに切り替えて、ユーザーがアプリケーションに戻ったときに動作がおかしくなり、静的オブジェクトがマルチタスクで削除されますか??? 何か案が ??また、シングルトンメソッドを介して静的オブジェクトを保持することをお勧めしますか?

回答:


238

少し背景から始めましょう:アプリケーションを起動するとどうなりますか?
OSはプロセスを開始し、一意のプロセスIDを割り当てて、プロセステーブルを割り当てます。プロセスは、DVM(Dalvik VM)のインスタンスを開始します。各アプリケーションはDVM内で実行されます。
DVMは、クラスロードのアンロード、インスタンスのライフサイクル、GCなどを管理します。

静的変数の存続期間:静的変数は、クラスがJVMによってロードされたときに存在し、クラスがアンロードされたときに終了します。

したがって、Androidアプリケーションを作成して静的変数を初期化した場合、次のいずれかが発生するまで、JVMに残り
ます。1。クラスがアンロードされる
2. JVMがシャットダウンする
3.プロセスが終了する

静的変数の値は、別のアプリケーションの別のアクティビティに切り替えても保持され、上記の3つが発生しないことに注意してください。上記の3つのいずれかが発生した場合、staticはその値を失います。

これを数行のコードでテストできます。

  1. アクティビティのonCreateで初期化されていない静的を出力します-> nullを出力します
  2. スタティックを初期化します。印刷->値はnull以外になります
  3. 戻るボタンを押して、ホーム画面に移動します。注:ホーム画面は別のアクティビティです。
  4. アクティビティをもう一度起動します->静的変数はnull以外になります
  5. DDMSからアプリケーションプロセスを強制終了します(デバイスウィンドウの停止ボタン)。
  6. アクティビティを再起動します->スタティックはnull値になります。

お役に立てば幸いです。


1
新しいアクティビティを開始するときに静的でない場合、アプリケーションオブジェクトのフィールド値が失われる理由を知りたいです。たとえば、アプリケーションオブジェクトで可変の現在のページを宣言し、新しいアクティビティを開くとその値が常にゼロに戻る
Mohammed Subhi Sheikh Quroush

super.onRestoreInstanceState(savedInstanceState);を呼び出すと、静的であっても変数を失うのですが、問題は何ですか?
Mohammed Subhi Sheikh Quroush 2013

1
これは良い説明です(だから-1はありません)が、それは少し重要ではありません。OPは、「メモリ不足の状況」(私がここにいる理由と同じ理由)について明示的に尋ねました。同じパラメータで、後でそれを再起動して、この場合は、(IF ...それは本当のことだ)ここに覆われていない
Rick77

1
@suitianshi Application.onCreateで静的インスタンスを初期化できると思います。アプリがバックグラウンドになり、プロセスが強制終了された場合でも、アプリに戻るとすぐに、Applicationクラスはインスタンス化され、対応するライフサイクルメソッドを呼び出します再び!これについて確認が必要ですが、Application.onCreateで初期化された静的インスタンスがその値を失うシナリオがあるのではないでしょうか。
Sarthak Mittal 2017

1
ここで欠けているのは、「1。クラスがアンロードされる」の説明です-これはいつ起こりますか?メモリが不足している場合、JVMはクラスをアンロードしますか?
stoefln

16

まあ、シングルトンパターンも静的変数の使用に基づいているので、実際には同じ位置にいます。静的なアプローチはほとんどの場合機能しますが、メモリがいっぱいになり、アプリケーションが次の画面に移動する前に別のアクティビティがフォアグラウンドになると、アクティビティのプロセスが強制終了され、静的な値が失われる場合があります。ただし、Androidには、状態間で値を永続化するか、値を送信するための次のようないくつかのオプションがあります。

  • インテントを使用すると、アクティビティ間で検索基準を渡すことができます(Web HTTPリクエストと同様)。
  • アプリケーション設定を使用して、値を保存し、それらを必要とするアクティビティで取得することができます
  • sqliteデータベースを使用すると、テーブルに永続化して後で取得できます
  • 再起動時にフィールドが以前に選択した値で満たされるようにアクティビティの状態を保存する必要がある場合は、onSaveInstanceState()アクティビティメソッドを実装できます。これは、アクティビティの状態の永続化間では推奨されないことに注意してください。

Googleコードまたは他のオープンソースのAndroidアプリケーションでaegis-shieldソースコードツリーを確認すると、プリファレンス、インテント、およびsqliteデータベースの使用例のコード例を入手できます。


6

いくつかの調査の結果、アプリケーションを使用してシングルトンを格納することは、それを再作成する準備ができていない限り、それほどすばらしいアイデアではないことがわかりました。

アプリケーションオブジェクトにデータを保存しない

したがって、受け入れられた答えは技術的には正しいですが、すべての情報を提供しているわけではありません。

上記のリンクが示すように、本当にそのモデルを使い続けたい場合は、nullをチェックし、可能であればデータを再作成する準備ができている必要があります。


3

@ r1k0はここです。クラスの静的フィールドにデータを保存すると、アプリケーションプロセスの強制終了と再起動の間、それ自体では永続しません。Androidは、メモリが必要な場合、プロセス(実行中のアプリ)を定期的に強制終了します。

Androidのドキュメントあたり:メモリから活動状態と排出

システムがアクティビティを直接強制終了することはありません。代わりに、アクティビティが実行されているプロセスを強制終了し、アクティビティだけでなく、プロセスで実行されている他のすべても破壊します。

以下のメソッドを使用して、プリミティブおよびSerializableオブジェクトとParcelableオブジェクトの状態を保存および復元できます。これらは、通常のアクティビティライフサイクル中に自動的に呼び出されます。

protected void onSaveInstanceState(Bundle state) {}
protected void onRestoreInstanceState(Bundle savedInstanceState){}

したがって、静的変数のみを持つクラスがある場合は、onSaveInstanceState()で各フィールドの状態を保存し、onRestoreInstanceState()でそれらを復元できます。Androidがアプリを実行しているプロセスを強制終了すると、変数の状態が保存され、Androidがアプリを復元すると、値は以前と同じ状態でメモリに復元されます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.