490

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

public class MyApp extends android.app.Application {

    private static MyApp instance;

    public MyApp() {
        instance = this;
    }

    public static Context getContext() {
        return instance;
    }

}

そして、コンテキストが必要な場所(もちろんSQLiteOpenHelperなど)にそれを渡しますか?

4

9 に答える 9

427

このアプローチにはいくつかの潜在的な問題がありますが、多くの状況(例など)ではうまく機能します。

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

また、パターンの代わりgetApplicationContext()に、Contextオブジェクト(アクティビティなど)を呼び出すショートカットを使用して、アプリケーションコンテキストを取得することもできます。

于 2009-06-12T16:00:30.393 に答える
30

私の経験では、このアプローチは必要ないはずです。何かのコンテキストが必要な場合は、通常、View.getContext()の呼び出しを介して取得でき、そこで取得したものを使用して、Context.getApplicationContext()Contextを呼び出してコンテキストを取得できます。からコンテキストを取得しようとしている場合は、いつでもActivity.getApplication()を呼び出すことができます。これは、への呼び出しに必要なものとして渡すことができるはずです。ApplicationApplicationActivityContextSQLiteOpenHelper()

全体として、この状況に対するアプローチに問題はないようですが、対処するときは、公式のGoogle Android DevelopersブログContextで説明されているように、どこにもメモリリークがないことを確認してください。

于 2009-06-12T15:57:54.393 に答える
14

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

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

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.xinstanceX.yinstancenullであることを示しています。変数X.xinstanceおよびY.yinstanceは、nullのときに読み取られたため、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

ただしApplication、これはAndroidオブジェクトのオプションではありません。プログラマーはオブジェクトが作成される時間を制御しません。

繰り返しますが、最初の例と2番目の例の違いは、静的ポインターがnullの場合、2番目の例がインスタンスを作成することです。ただし、プログラマーは、システムが作成を決定する前にAndroidアプリケーションオブジェクトを作成することはできません。

アップデート

初期化された静的フィールドがたまたまであるもう1つの不可解な例null

Main.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行上に移動することはできず、コードはコンパイルされないことに注意してください。

于 2013-12-09T06:17:20.657 に答える
12

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

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()
于 2016-08-13T10:37:44.237 に答える
8

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

Context.getApplicationContext() 私の理解によると、2またはのいずれかを呼び出すためのより良いアプローチを推測します Activity.getApplication()

于 2010-06-21T06:55:20.543 に答える
5

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

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

個人的には、通常、Applicationをサブクラス化する必要はないと言っているので、ドキュメントが間違っていると思います。逆のことが当てはまると思います。常にApplicationをサブクラス化する必要があります。

于 2013-08-07T12:46:20.830 に答える
3

アプリケーションコンテキストを使用して、コンストラクターでシステムサービスを取得します。これにより、テストが容易になり、構成によるメリットが得られます

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

}

次に、テストクラスはオーバーロードされたコンストラクターを使用します。

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

于 2014-06-27T08:45:49.323 に答える
1

私はそれが好きですが、代わりにシングルトンを提案します:

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;
    }
}
于 2011-02-23T22:49:33.077 に答える
0

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

public static MyApp getInstance() {

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

    return instance;
}

しかし、私はどこでも使用しているわけgetContext()getApplicationContext()はありません。

于 2013-06-05T13:52:01.537 に答える