2016-12-31 13 views
3

シングルトンクラスからアプリケーションリソース(特定の文字列リソース)にアクセスしようとしています。 Singletonなので、このクラスは(メモリリークを防ぐために)Contextオブジェクトへの参照を保持することはできません。静的参照を使用しないコンテキストの使用

  1. アプリケーションクラスで静的コンテキストを作成し、アプリケーション全体で使用します。ネット上で他の実装を探していました。
  2. コンテキストを必要なメソッドのパラメータとして渡します。

私はContextオブジェクトへの静的参照を使用するので、拳1を使いたくありません。私はそれがアンドロイドのアプリケーションクラスで静的に持っていても大丈夫だと理解していますが、それでもハックのように見えます。

シングルトンのsomeOtherMethodに渡すことのできるコンテキストのインスタンスがないため、2番目の実装は役に立ちません。

私はシングルトンのインスタンスを初期化するときに、シングルトンのインスタンスを初期化するときに、シングルトンのアブストラクトをメソッドの必要性をオーバーライドするように実装しました(例:getString(int resId))。

これでメモリリークが発生する可能性があるのか​​どうか不思議です。私はこのアプローチと混同しています

- オーバーライドgetStringのコンテキストへ>参照が最終です。メモリリークの原因になるかどうかはわかりません。

public abstract class SingletonClass{ 

    . 
    . 
    . 

    private static SingletonClass sInstance; 

    private SingletonClass(Context paramContext) { 
     // constructor code 
    } 

    public static SingletonClass getInstance(final Context context) { 
     if (sInstance == null) { 
      sInstance = new SingletonClass(context){ 
       @Override 
       public String getString(int resId) { 
        return context.getString(resId); 
       } 
      }; 
     } 
     return sInstance; 
    } 

    public abstract String getString(int resId); 

    . 
    . 
    . 

    private void someOtherMethod(){ 
     //uses above getString() 
    } 

    } 
+0

これらの文字列をどのように使用しているかを共有できますか。具体的には、使用するときに「コンテキスト」を持たないのはなぜですか?ほとんどの場合、Activity/Service/BroadcastReceiver/SQLiteOpenHelper /などがコンテキストを提供し、シングルトンをいくらか不要にします。 – chessdork

+0

アンドロイドゲームでGoogle Playゲームサービスを使用しています。私は単一のGoogleApiClientをアプリ全体に保持する必要があるので、シングルトンを考えました。 –

答えて

0

あなたのアプローチにはメモリリークがあります。 getInstanceに渡された最初のコンテキストは、匿名クラスが参照を保持しているので、ガベージコレクションされません。 (そして、匿名クラスへの静的な参照があります)。たとえば、getInstance(Activity)に電話をかけた場合、そのアクティビティはプロセスが終了するまでメモリに残ります。

幸いにも、メモリリークを取り除くには非常に簡単な修正があります。あなたはアプリケーションコンテキスト(context.getApplicationContext)を安全に保持することができます。これは基本的に、アプリケーションの存続期間中のシングルトンコンテキストです。

public static SingletonClass getInstance(Context c) { 
    if (sInstance == null) { 
     sInstance = new SingletonClass(c.getApplicationContext()); 
    } 
    return sInstance; 
} 
0

onResumeメソッドでシングルトンオブジェクトへの参照を渡し、onPauseでアクティビティをクリーンアップする必要があります。

protected void onResume() { 
    super.onResume(); 
    Singleton.getInstance().onResume(this); 
} 

protected void onPause() { 
    super.onResume(); 
    Singleton.getInstance().onPause(); 
} 

また、あなたはContextのインスタンスを更新しWeakReferenceでそれを保持することができます:

class Singleton { 
    private WeakReference<Context> mContext; 

    private boolean hasContext() { 
    return mContext != null && mContext.get() != null; 
    } 

    public static Singleton getInstance(Context c) { 
    //do your singleton lazy 
    if (!sInstance.hasInstance()) { 
     sInstance.mContext = new WeakReference<>(c); 
    } 
    return sInstance; 
    } 
} 

第二の場合は、仕上げの活動への参照を保持することができたので、私はそれを示唆していません。

+0

'Singleton'は何か非同期をやっていますか?'Context'が突然' null'を取得すると、エラーが発生します。そうではありませんか? –

+0

@AnkitMundadaあなたのコンテキストがnullになる場合、あなたはもうコンテキストとは関係ありません。コンテクストがリソースに対してnullの場合、nullを返すことができます。 –

+0

あなたの最初のメソッドでは、 'onResume()'の文脈をきれいにするが、それでも 'Singleton'の非同期呼び出しでまだ使用されているのであれば、例外をスローしませんか?それはまだ非同期のプロセスによって使用されている場合、なぜあなたはもうコンテキストとは何の関係もないと言っていますか? –

関連する問題