質問

Android アプリでは、次のアプローチに問題はありますか。

public class MyApp extends android.app.Application {

    private static MyApp instance;

    public MyApp() {
        instance = this;
    }

    public static Context getContext() {
        return instance;
    }

}

そしてそれをどこにでも渡します(例:SQLiteOpenHelper) コンテキストが必要な場合 (もちろんリークはありません)?

役に立ちましたか?

解決

(たとえば、あなたの例のような)状況の多くでは、それはうまく動作しますが、このアプローチの潜在的な問題がいくつかあります。

GUIを必要とするContextを扱うものを扱うときに

特に、あなたは注意する必要があります。たとえば、LayoutInflaterあなたが例外を取得するにアプリケーションコンテキストを渡す場合。一般的に言えば、あなたのアプローチが優れている:超えコンテキストを渡すときには、Activity'sその内の Context Activity をを使用することをお勧めします、そしてApplication Context Activityの範囲は、メモリリークを避けますのます。

また、あなたのパターンへの代替のようあなたがアプリケーション・コンテキストを取得するために(たとえば、活動など)の getApplicationContext() のオブジェクトにContextを呼び出すショートカットを使用することができます。

他のヒント

私の経験では、このアプローチは必要ありません。あなたは何のためのコンテキストが必要な場合は、通常、<のhref =「http://developer.android.com/reference/android/view/View.html#getContext()」のrel = "nofollowをnoreferrerへの呼び出しを介してそれを得ることができます"> View.getContext()とが得Contextを使用してあなたが呼び出すことができます<のhref =" http://developer.android.com/reference/android/content/Context.html#getApplicationContext()」REL = "nofollowをnoreferrer"> Context.getApplicationContext()のはApplicationコンテキストを取得します。あなたはApplicationからこれをActivityコンテキストを取得しようとしている場合は、常に<のhref =「http://developer.android.com/reference/android/app/Activity.html#getApplication()」のrel = "nofollowを呼び出すことができますContextの呼び出しのために必要SQLiteOpenHelper()として渡すことができるようにする必要がありnoreferrer "> Activity.getApplication()のます。

全体的に、このような状況のためにあなたのアプローチに問題があるとは思えませんが、Contextを扱うときだけ<のhref = "HTTP公式に説明するように、あなたがどこにもメモリリークしていないことを確認してください:// android- developers.blogspot.com/2009/01/avoiding-memory-leaks.html」のrel = "nofollowをnoreferrer"> GoogleのAndroid開発者ブログでます。

一部の人は次のように尋ねました。 シングルトンはどのようにして null ポインタを返すことができるのでしょうか?その質問に答えています。(コードを投稿する必要があるため、コメントでは回答できません。)

2 つのイベントの間では null を返す場合があります。(1) クラスがロードされ、(2) このクラスのオブジェクトが作成されます。以下に例を示します。

class X {
    static X xinstance;
    static Y yinstance = Y.yinstance;
    X() {xinstance=this;}
}
class Y {
    static X xinstance = X.xinstance;
    static Y yinstance;
    Y() {yinstance=this;}
}

public class A {
    public static void main(String[] p) {
    X x = new X();
    Y y = new Y();
    System.out.println("x:"+X.xinstance+" y:"+Y.yinstance);
    System.out.println("x:"+Y.xinstance+" y:"+X.yinstance);
    }
}

コードを実行してみましょう:

$ javac A.java 
$ java A
x:X@a63599 y:Y@9036e
x:null y:null

2 行目は次のことを示しています Y.xインスタンス そして X.yinstanceヌル;変数が null であるため、 X.xインスタンス 答え Y.yインスタンス null のときに読み取られました。

これは修正できますか?はい、

class X {
    static Y y = Y.getInstance();
    static X theinstance;
    static X getInstance() {if(theinstance==null) {theinstance = new X();} return theinstance;}
}
class Y {
    static X x = X.getInstance();
    static Y theinstance;
    static Y getInstance() {if(theinstance==null) {theinstance = new Y();} return theinstance;}
}

public class A {
    public static void main(String[] p) {
    System.out.println("x:"+X.getInstance()+" y:"+Y.getInstance());
    System.out.println("x:"+Y.x+" y:"+X.y);
    }
}

このコードには異常はありません。

$ javac A.java 
$ java A
x:X@1c059f6 y:Y@152506e
x:X@1c059f6 y:Y@152506e

しかし これは Android のオプションではありません Application 物体:プログラマは、それが作成される時間を制御しません。

もう一度:最初の例と 2 番目の例の違いは、2 番目の例では静的ポインターが null の場合にインスタンスを作成することです。でもプログラマーは作れない システムが実行を決定する前の Android アプリケーション オブジェクト。

アップデート

初期化された静的フィールドがたまたま次のような不可解な例です。 null.

メイン.java:

enum MyEnum {
    FIRST,SECOND;
    private static String prefix="<", suffix=">";
    String myName;
    MyEnum() {
        myName = makeMyName();
    }
    String makeMyName() {
        return prefix + name() + suffix;
    }
    String getMyName() {
        return myName;
    }
}
public class Main {
    public static void main(String args[]) {
        System.out.println("first: "+MyEnum.FIRST+" second: "+MyEnum.SECOND);
        System.out.println("first: "+MyEnum.FIRST.makeMyName()+" second: "+MyEnum.SECOND.makeMyName());
        System.out.println("first: "+MyEnum.FIRST.getMyName()+" second: "+MyEnum.SECOND.getMyName());
    }
}

そして、次のものが得られます。

$ javac Main.java
$ java Main
first: FIRST second: SECOND
first: <FIRST> second: <SECOND>
first: nullFIRSTnull second: nullSECONDnull

静的変数宣言を 1 行上に移動することはできないことに注意してください。コードはコンパイルされません。

あなたは、アプリケーション・コンテキストを取得するためにラッパーを作成しようとしていると、それは「null」ポインタを返す可能性がある。

私の理解あたりとして、私は2のいずれかをcall-してより良いアプローチを推測します Context.getApplicationContext()またはActivity.getApplication()ます。

アプリケーションクラスます:

import android.app.Application;
import android.content.Context;

public class MyApplication extends Application {

    private static Context mContext;

    public void onCreate() {
        super.onCreate();
        mContext = getApplicationContext();
    }

    public static Context getAppContext() {
        return mContext;
    }

}

AndroidManifestでアプリケーションを宣言します:

<application android:name=".MyApplication"
    ...
/>

使用方法:

MyApplication.getAppContext()

これは良いアプローチです。私も自分自身をそれを使用しています。私は、コンストラクタを使用する代わりにシングルトンを設定するonCreateをオーバーライドすることをお勧めします。

そして、あなたはSQLiteOpenHelperを言及したのは:onCreate ()ではあなたにも、データベースを開くことができます。

個人的に私は、ドキュメントは、のアプリケーションのをサブクラス化する必要は通常ありませんと言って、それが間違ってましたと思います。私は反対が本当だと思う:あなたは常に、サブクラスアプリケーションをすべきである。

私はコンストラクタでシステムサービスを取得するためにアプリケーション・コンテキストを使用します。これは、組成物からテスト&メリットが容易になります。

public class MyActivity extends Activity {

    private final NotificationManager notificationManager;

    public MyActivity() {
       this(MyApp.getContext().getSystemService(NOTIFICATION_SERVICE));
    }

    public MyActivity(NotificationManager notificationManager) {
       this.notificationManager = notificationManager;
    }

    // onCreate etc

}

Testクラスは、オーバーロードされたコンストラクタを使用することになります。

のAndroidはデフォルトコンストラクタを使用します。

私はそれが好き、私は代わりにシングルトンをお勧めします:

package com.mobidrone;

import android.app.Application;
import android.content.Context;

public class ApplicationContext extends Application
{
    private static ApplicationContext instance = null;

    private ApplicationContext()
    {
        instance = this;
    }

    public static Context getInstance()
    {
        if (null == instance)
        {
            instance = new ApplicationContext();
        }

        return instance;
    }
}

私は同じアプローチを使用しています、私は少し良くシングルトンを書くことをお勧めします:

public static MyApp getInstance() {

    if (instance == null) {
        synchronized (MyApp.class) {
            if (instance == null) {
                instance = new MyApp ();
            }
        }
    }

    return instance;
}

が、私は、私はそれを行うことができますgetContext()getApplicationContext()を使用し、どこにでも使用していないよ!

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top