2009-10-28 4 views
14

アクティビティのいくつかの呼び出し(つまり、いくつかのonCreate()/ onDelete()サイクル)を経て状態を保持しなければならないという問題が頻繁に発生します。残念なことに、そのためのAndroidのサポートは実際には貧弱です。アクティビティクラスの静的フィールドは、作成/破棄サイクルよりも寿命が長くなることが保証されていますか?

状態を保存する簡単な方法として、クラスはクラスローダーによって一度しかロードされないため、静的なBundleフィールドのアクティビティの複数のインスタンス間で共有される一時的なデータを格納することが安全だと思いました。

ただし、インスタンスAが静的バンドルを作成してその中にデータを格納した後、インスタンスBがそれを読み込もうとすると、静的フィールドが突然NULLになります。

これは、アクティビティが作成/破棄のサ​​イクルを経ている間に、クラスローダーによってクラスが削除され、再ロードされたことを意味しませんか?どのようにしてのstaticフィールドがオブジェクトを参照していたときに突然NULLになる可能性がありますか?

+0

わからないが、私はAndroidの開発者は、メモリへの傾向があるとして、あなたが、不必要に静的な参照を保持しないことをお勧めしますことを知っています漏れ:http://android-developers.blogspot.com/2009/01/avoiding-memory-leaks.html – I82Much

+2

まあ、その記事はContextsを漏らすことです。これは、コンテキストがその静的参照を介して強く到達可能である場合の唯一の懸念事項である。ビューは表示されますが、バンドルは表示されません(私が知る限り)。しかし、一般的に私は、クラスが読み込まれると、静的な参照は、Androidの中で真実ではないように見える限り、アプリケーションと同じくらい長く存続すると仮定します。 – Matthias

答えて

13

この答えの最初の部分は本当に古いです - それは

あなたはストアアプリケーションの永続オブジェクトへのアプリケーションのオブジェクトを使用することができます行うには権利方法については、以下を参照してください。 This Android FAQもこの問題について話しています。

このような何か:

public class MyApplication extends Application{ 
    private String thing = null; 

    public String getThing(){ 
     return thing; 
    } 

    public void setThing(String thing){ 
     this.thing = thing; 
    } 
} 

public class MyActivity extends Activity { 
    private MyApplication app; 

    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 

     app = ((MyApplication)getApplication()); 

     String thing = app.getThing(); 
    } 
} 

方法:この答えが最初に書かれた

、活動のライフサイクルのドキュメントは、それが今ほど良くありませんでした。アクティビティ文書のSaving Activity Stateセクションを読むと、Androidがどのように状態を保存するかを理解するのに役立ちます。基本的に、あなたの活動が始まる2つの状況があります:(1)新しい活動として、(2)構成の変更またはメモリ圧迫のために破壊された後に再作成されるためです。新しいアクティビティであるためにアクティビティが開始されると、saveInstanceStateはnullになります。それ以外の場合はnullではありません。 nullの場合は、アクティビティを最初から初期化する必要があります。フラグメントはアクティビティと非常によく似ています。私はこの概念を私のAnDevCon-14 slide deckについて詳しく説明しました。詳細については、AnDevCon-14プレゼンテーションのsample codeをご覧ください。

私の前の例は、以下のコードのようになります。私はセマンティクスを少し変更する - この2番目のバージョンでは、文字列thingが特定のandroid task内のアクティビティに固有であると仮定します。前の例ではあいまいです。複数のアンドロイドタスクのために同じデータを保持したい場合は、アプリケーションオブジェクトまたは別のシングルトンのいずれかを使用することが最良の方法です。

public class MyActivity extends Activity { 
    private static final String THING = "THING"; 

    private String thing; 

    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 

     if (savedInstanceState==null) { 
      // First time here (since we last backed out at least) 
      thing = initializeThing(); // somehow we init it 
     } else { 
      // Rehydrate this new instance of the Activity 
      thing = savedInstanceState.getString(THING); 
     } 

     String thing = app.getThing(); 
    } 

    protected void onSaveInstanceState(Bundle outState) { 
     outState.putString(THING, thing); 
    } 
} 
+4

実際にはかなり良いと簡単なアイデアです...神のオブジェクトのパターンに変わらない限り – Matthias

+0

Hehe、私は神のオブジェクト[1]パターンの前に聞いていない。かなり面白いもの。おそらくこれは単なる例に過ぎないと言っていたはずです。簡単なアプリケーション以上のものであれば、アプリケーションクラスには、データそのもののリポジトリではなく、実際のデータを保持する他のオブジェクトが存在するだけです。他のオブジェクトを格納するためのAndroidの便利な場所です。 [1] http://en.wikipedia.org/wiki/God_object – JohnnyLambada

+1

私は、Applicationクラスを変更して、シングルトンを使う方向に向かっています。 Dianne Hackbodの回答を参照してください:http://stackoverflow.com/questions/3826905/singletons-vs-application-context-in-android – JohnnyLambada

0

静的なデータを保持するもう一つの悪い方法は、あなたにシングルトンクラスをスピンアップさせることです。このシングルトンは、自身への静的な参照を保持します。

class EvilSingleton{ 
    private static EvilSingleton instance; 

    //put your data as non static variables here 

    public static EvilSingleton getInstance() 
    { 
     if(instance == null) 
      instance = new EvilSingleton(); 
     return instance; 
    } 
} 

アクティビティのonCreate()メソッドでは、シングルトンと必要なすべてのデータにアクセス/構築できます。そうすれば、あなたの活動やアプリケーションが何回も破壊されたり再現されたりすることがあります。プロセスのメモリスペースが保存されている限り、になります。

これは邪悪な破壊ハックですので、あなたの質問への答えがない約束;-)

+2

ありがとう、ありがとうございます。私はシングルトンで十分楽しんだ。それは最も酷使されたデザインパターンです。ほとんどの場合、使用されているのを見ましたが、実際には反パターンでした。 – Matthias

+0

十分に公正。それはあまりパターンではありません、私は大規模なスケジュールの圧力の下でそれらを使用しましたが、私は大規模で、よく維持されたプロジェクトで、彼らはせいぜい控えめに使用する必要があります。 – haseman

+0

シングルトンの防衛のために、AndroidではSqliteOpenHelperインスタンスが適しています。それ以外は、皆さんに同意します。 –

関連する問題