2016-09-29 21 views
-1

Androidのアクティビティの管理方法がわかりません。Androidのアクティビティがランダムに作成され、破棄される

私は一度の私は私のアプリがバックグラウンドに入るとき、気づいていながら、中の活動とを持っている、現在の活動は、(たとえばActivity3)であるものは何でもアンドロイド破棄および他のいくつかのシングルトンやオブジェクトなどのthatsの罰金。問題は、アプリが再開された直後に、アンドロイドがアクティビティやオブジェクトをメモリなどで破壊してから、アンドロイドがアプリを完全に再起動するということです。アクティビティ1からすべてのオブジェクトとデータメンバーが適切に初期化されます。

NOT SO!

すべてこれだけの時間私のアプリが再開されたとき、Activity3が再作成され、のonCreateが、(それがActivity2から呼ばれた)は初めてだったのと同じパラメータで呼び出されているようですシングルトンなどのオブジェクトは、アクティビティ1およびで初期化されました。アクティビティ2はデフォルト値で再作成され、役に立たなくなりました。

これはどのように安全なポリシー/手法ですか?どうやってアンドロイドはオブジェクトやアクティビティをランダムに破壊することができますか?そして、ユーザーが最近のアクティビティでonCreateを呼び出すだけで、すべてが大事になると期待しては正しいスタートアップ手順/初期化を実行する必要はありませんか?

UPDATE/SOLUTIONその優れた情報のためのコメント主に

感謝。アンドロイドマニュアルに従って

のonCreate

バンドル:アクティビティが以前にシャットダウンされた後に再初期化されている場合、このバンドルは、それが最近onSaveInstanceState(バンドル)に供給されたデータが含まれています。注:それ以外の場合はnullです。

したがって、私がやったことは、2つのフラグを設定することです。 onSaveInstanceStateをバンドルに入れて、それが私によって設定された有効なバンドルであることを確認してください。クラスそのものの中でを作成したかどうかを確認するには、レクリエーションまたはの自動回転のために呼び出されました。したがって、のonCreateの場合、onSaveInstanceStateがnullでないかどうかを確認し、バンドルフラグをチェックしてbInit(デフォルトはfalse)をチェックします。両方のフラグが真であれば、アンドロイドがダンプされ、アプリのメモリが破壊されたことを意味します。リニアスタイルのアプリケーションですべてが初期化されることを確実にする最も安全な方法は、それを再起動して開始アクティビティを開始することです。

public class SomeMiddleActivity extends AppCompatActivity 
{ 
    private static boolean bInit = false; // only way it will be false again is if android cleared our memory and we are recreating 

    @Override 
    public void onSaveInstanceState(Bundle state) 
    { 
     // set a flag so that onCreate knows this is valid 
     state.putBoolean("StateSaved", true); 
     super.onSaveInstanceState(state); 
    } 

    @Override 
    protected void onCreate(Bundle savedInstanceState) 
    { 
     // this must be called first always for some reason 
     super.onCreate(savedInstanceState); 

     if (savedInstanceState != null) 
     { 
      if (savedInstanceState.getBoolean("StateSaved", false) && !bInit) 
      { 
       // we were recreated... start app over 
       Intent intent = new Intent(getApplicationContext(), Startup.class); 
       startActivity(intent); 
       finish(); 
       return; 
      } 
     } 

     bInit = true; // this will stay true until android has cleared our memory 

     ....... 
    } 

これまでのところこれまではうまくいきましたが、誰かが別の提案をしてくれれば教えてください。私はこれについて別の記事を掲載します。

とFYI:onSaveInstanceState(バンドル、PersistableBundle)onSaveInstanceStateバージョンは、これまでと呼ばれることはありませんので、私は、彼らもそれを実装する理由を知りません。 (?)

@goldenb @Rishabh洞察のためにgoldenbとRishabhに感謝します。

+0

あなたのタイトルから 'SOLVED'を削除し、適切として発見ソリューションを投稿してください答え(つまり、与えられた答えの1つと正確に同じでない場合)。 – usr2564301

+0

投稿する場所?.... – zdanman

+0

"Your Answer"と表示された大きな空のボックスに、以下のソリューションがあります。 – usr2564301

答えて

1

Androidは、破壊すると、それを処理するツールも提供します。

モバイルデバイスは、同時に実行されているアプリケーション間で共有する必要があるメモリ容量が限られています。したがって、スマートリソースの割り当てが必要です。フォアグラウンドで実行されているアプリケーションは、エンドユーザーによって使用され、パフォーマンスとユーザーエクスペリエンスを向上させるために高い優先順位を得ています。したがって、バックグラウンドで実行されるアプリケーションは、フォアグラウンドアプリケーションのメモリ要件を満たすためにリソースを解放する必要があります。したがって、バックグラウンドアプリケーションは、(メモリが不足している場合)時には(完全ではなく)破壊されます。

Androidの活動は、コールバックがonSaveInstanceState()とonRestoreInstanceStateが好き持っている()活動のあなたの現在の状態を保存することができます(すなわち、変数の値)、それは破壊され、活動が再作成されたときにそれらを取得しています。

あなたはここからより多くの情報を得ることができます。How to save and retrieve the state of Activity using onSaveInstanceState and onRestoreInstanceState.

あなたは活動を確保するためにretreived状態で検証を行うことができますが、それは前の破壊をしていたとおりに実行されます。一度手に入れば、それは非常に簡単で論理的です。

+0

インスタンスが再開されたときにアプリケーションを完全に再起動する方法はありますか? – zdanman

+1

回避策があります(プロセスを強制終了して再起動するなど)が推奨されていません。むしろ、アクティビティタスクスタックをクリアして(インテントフラグを使用して)、ランチャーアクティビティを開始することができます(必要に応じて、ユーザに通知することができます)。 –

+0

これをあなたに任せてください。 ** onSaveInstanceState **の** System.exit(0)**または** finish()**を呼び出すとどうなりますか?私の理解から** onSaveInstanceState **が呼び出され、アプリがバックグラウンドにありメモリからクリアされているときに_only_が呼び出されます。これにより、ユーザーがアプリアイコンを再び押すたびにアプリが起動されます。 – zdanman

1

問題に50セントをおいてください。バックグラウンドでそのリソースのためにシステムによって殺された活動の問題に対処する正しい方法は、アンドロイドの共通の問題です.Googleによると、これに関する解決策は次のとおりです:

onPauseユーザーはあなたの活動を離れます。ほとんどの場合、 が重要です。ユーザーが行った変更は、この時点で (通常はデータを保持するContentProvider)にコミットする必要があります。

強調は私のものです。しかし、これが意味することは、Androidのライフサイクルは、通常の条件では、ActivityまたはFragmentがバックグラウンドで送信されるときにonPauseを呼び出すように設計されているということです。

アクティビティが一時停止状態になると、システムはあなたのアクティビティでonPause()メソッドを呼び出します。これにより、一時停止中に継続してはならない継続的なアクションを停止することができます)またはユーザーがあなたのアプリを離れるのを続ける場合には、永久に保存する必要のある情報を残してください()。また

あなたの注意に値する:あなたはビューがActivity recreation時に復元されることを望むなら、あなたはすべてのビューのID属性を設定しておく必要があります;)

注:Androidのシステムのために復元しますあなたのアクティビティの ビューの状態です。各ビューは、 によって提供される一意のIDを持つ必要があります。

PS。 あなたがonSaveInstanceState(バンドル、PersistableBundle)が呼び出されない理由は、一つの可能​​性はあなたが右のアクティビティ属性が

を設定していないということです不思議に思った。これはonRestoreInstanceState(バンドル)と同じですが のために呼ばれています persistAcrossRebootsに属性persistableModeセットで作成活動..

+1

ところで、デバイスを回転させると、これらの問題のいくつかが発生しているはずです。あなたは間違いなくonPause()の間にあなたのデータを永続させるべきです。 ;) – HenriqueMS

+0

これを持っていただきありがとうございます。 ** onRestoreInstanceState **が回転中に呼び出されたことを忘れていました。私がしたことは、デフォルトでfalseであるメモリにフラグ** bInit **を追加することでした。これは、回転またはレクリエーションのためにonCreateが呼び出されたかどうかを教えてくれます。上記の記事を更新しました。 – zdanman

関連する問題