web-dev-qa-db-ja.com

Androidグローバルコンテキストのシングルトン

Android Documentationによると:

通常、アプリケーションをサブクラス化する必要はありません。ほとんどの場合、静的シングルトンは同じ機能をよりモジュール化された方法で提供できます。シングルトンにグローバルコンテキストが必要な場合(ブロードキャストレシーバーの登録など)、それを取得する関数には、シングルトンを最初に構築するときにContext.getApplicationContext()を内部的に使用するコンテキストを指定できます。

アプリで実行中のアクティビティの変化に耐えられるように、グローバルコンテキストを持つ静的シングルトンを作成するにはどうすればよいですか? getApplicationContext()を参照する静的コンテキストがあれば十分ですか?

43
Derek Gebhard

質問への別の編集:

最近(2016年以降のほとんど)、私がやってきたこと、そしてそれを行うためにすべての開発者に私の提案になるでしょう:

Dagger2を使用するだけで、Dagger 2を使用します。Contextが必要な場合はいつでも:

@Inject Context context;

以上です。その間に、シングルトンになる他のすべてのものを注入します。

編集/改善された回答:

この回答は一般的になっているため、最近(2014年7月現在)使用しているサンプルコードを使用して、独自の回答を改善します。

アプリケーションが自身への参照を保持することから始めます。

public class App extends Application {
   private static App instance;
   public static App get() { return instance; }

   @Override
   public void onCreate() {
      super.onCreate();
      instance = this;
   }
}

次に、contextへのアクセスを必要とするシングルトンで、ここで説明するようにダブルチェック同期を使用してスレッドセーフな方法でシングルを遅延ロードします https://stackoverflow.com/a/11165926/906362

private static SingletonDemo instance;

public static SingletonDemo get() {
   if(instance == null) instance = getSync();
   return instance;
}

private static synchronized SingletonDemo getSync() {
   if(instance == null) instance = new SingletonDemo();
   return instance;
}

private SingletonDemo(){
   // here you can directly access the Application context calling
   App.get();
}

元の回答:

ドキュメントが示唆しているのは、 通常のシングルトンパターン を使用することです

 public class SingletonDemo {
    private static SingletonDemo instance = null;

    private SingletonDemo() {       }

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

そしてその中に次のようなメソッドを含めます:

 private Context context;
 init(Context context){
    this.context = context.getApplicationContext();
 }

そして、これを呼び出してシングルトンを初期化することを忘れないでください。

アプリケーションアプローチとシングルトンアプローチの違い、およびシングルトンが優れている理由は、ドキュメントsame functionality in a more modular way

83
Budius

私のアプリケーションにはそのようなクラスがあります:

public class ApplicationContext {

    private Context appContext;

    private ApplicationContext(){}

    public void init(Context context){
        if(appContext == null){
            appContext = context;
        }
    }

    private Context getContext(){
        return appContext;
    }

    public static Context get(){
        return getInstance().getContext();
    }

    private static ApplicationContext instance;

    public static ApplicationContext getInstance(){
        return instance == null ?
                (instance = new ApplicationContext()):
                    instance;
    }
}

そして、例えばLaunch Activityでそれを初期化します:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    //init
    ApplicationContext.getInstance().init(getApplicationContext());
    //use via ApplicationContext.get()
    assert(getApplicationContext() == ApplicationContext.get());
}
4
Mickey Tin