1064

Context静的メソッド内で現在のインスタンスを取得する方法はありますか?

「コンテキスト」インスタンスが変更されるたびに保存するのが嫌いなので、その方法を探しています。

4

21 に答える 21

1381

これを行う:

Android マニフェスト ファイルで、次のように宣言します。

<application android:name="com.xyz.MyApplication">

</application>

次に、クラスを記述します。

public class MyApplication extends Application {

    private static Context context;

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

    public static Context getAppContext() {
        return MyApplication.context;
    }
}

MyApplication.getAppContext()アプリケーションコンテキストを静的に取得するためにどこでも呼び出します。

于 2011-02-25T06:37:00.513 に答える
66

アプリケーションコンテキストを取得することについて話していると仮定すると、アプリケーションを拡張する@Rohit Ghatolによって提案されたように実装しました。その場合、そのような方法で取得されたコンテキストが常に非 null であるという保証はありません。ヘルパーを初期化するか、リソースを取得する必要があるときは、通常、時間を遅らせることはできません。null ケースを処理しても役に立ちません。ドキュメントに記載されているように、基本的にAndroidアーキテクチャと戦っていることを理解しました

注: 通常、Application をサブクラス化する必要はありません。ほとんどの場合、静的シングルトンは、よりモジュール化された方法で同じ機能を提供できます。シングルトンにグローバル コンテキストが必要な場合 (ブロードキャスト レシーバーを登録する場合など)、シングルトンの getInstance() メソッドを呼び出すときに Context 引数として Context.getApplicationContext() を含めます。

ダイアン・ハックボーンによる説明

Application が派生元として存在する唯一の理由は、1.0 より前の開発中に、アプリケーション開発者の 1 人が、より「通常の「彼らのアプリケーション モデルに、そして私は最終的に屈服しました。私はそのモデルに屈したことを永遠に後悔します。:)

彼女はまた、この問題の解決策を提案しています。

アプリのさまざまな部分で共有できるグローバルな状態が必要な場合は、シングルトンを使用します。[...] そして、これは、これらのものをどのように管理すべきか、つまり必要に応じて初期化する方法に自然につながります。

だから私がしたことは、アプリケーションの拡張を取り除き、プライベートコンストラクターでアプリケーションコンテキストへの参照を保存しながら、コンテキストをシングルトンヘルパーの getInstance() に直接渡すことでした:

private static MyHelper instance;
private final Context mContext;    

private MyHelper(@NonNull Context context) {
    mContext = context.getApplicationContext();
}

public static MyHelper getInstance(@NonNull Context context) {
    synchronized(MyHelper.class) {
        if (instance == null) {
            instance = new MyHelper(context);
        }
        return instance;
    }
}

呼び出し元はローカル コンテキストをヘルパーに渡します。

Helper.getInstance(myCtx).doSomething();

したがって、この質問に適切に答えるには、アプリケーション コンテキストに静的にアクセスする方法がありますが、それらはすべてお勧めできません。ローカル コンテキストをシングルトンの getInstance() に渡すことをお勧めします。


興味のある方は、 fwd ブログでより詳細なバージョンを読むことができます

于 2016-08-16T05:36:06.690 に答える
51

いいえ、ないと思います。残念ながら、またはの他のサブクラスの 1getApplicationContext()つからの呼び出しがスタックしています。また、この質問は多少関連しています。ActivityContext

于 2010-01-05T00:46:00.533 に答える
40

これは、UI スレッドのどこからでもアプリケーション(コンテキスト)を取得する、文書化されていない方法です。非表示の静的メソッドに依存しています。少なくとも Android 4.x では動作するはずです。ActivityThread.currentApplication()

try {
    final Class<?> activityThreadClass =
            Class.forName("android.app.ActivityThread");
    final Method method = activityThreadClass.getMethod("currentApplication");
    return (Application) method.invoke(null, (Object[]) null);
} catch (final ClassNotFoundException e) {
    // handle exception
} catch (final NoSuchMethodException e) {
    // handle exception
} catch (final IllegalArgumentException e) {
    // handle exception
} catch (final IllegalAccessException e) {
    // handle exception
} catch (final InvocationTargetException e) {
    // handle exception
}

UI スレッドの外部でメソッドを呼び出した場合や、アプリケーションがスレッドにバインドされていない場合など、このメソッドが null を返す可能性があることに注意してください。

アプリケーションコードを変更できる場合は、@ RohitGhatolのソリューションを使用することをお勧めします。

于 2012-09-19T13:34:04.167 に答える
33

コンテキストを何に使用しているかによって異なります。この方法には、少なくとも 1 つの欠点が考えられます。

AlertDialogwithを作成しようとしている場合AlertDialog.BuilderApplicationコンテキストは機能しません。現在のコンテキストが必要だと思いますActivity...

于 2011-08-12T01:07:38.100 に答える
12

RoboGuiceを使用することに慣れている場合は、必要なクラスにコンテキストを挿入できます。これは、RoboGuice 2.0(この記事の執筆時点ではベータ4)でそれを行う方法の小さなサンプルです。

import android.content.Context;
import android.os.Build;
import roboguice.inject.ContextSingleton;

import javax.inject.Inject;

@ContextSingleton
public class DataManager {
    @Inject
    public DataManager(Context context) {
            Properties properties = new Properties();
            properties.load(context.getResources().getAssets().open("data.properties"));
        } catch (IOException e) {
        }
    }
}
于 2012-02-29T14:46:28.267 に答える
9

私はある時点でこれを使用しました:

ActivityThread at = ActivityThread.systemMain();
Context context = at.getSystemContext();

これは、私がシステム サービスを取得する際に使用し、機能した有効なコンテキストです。

ただし、フレームワーク/ベースの変更でのみ使用し、Android アプリケーションでは試しませんでした。

知っておくべき警告: このコンテキストでブロードキャスト レシーバーを登録すると、機能せず、次のようになります。

java.lang.SecurityException: 指定された呼び出し元パッケージ android がプロセス ProcessRecord で実行されていません

于 2014-05-08T10:22:50.943 に答える
5

このソースによると、 ContextWrapper を拡張することで独自のコンテキストを取得できます

public class SomeClass extends ContextWrapper {

    public SomeClass(Context base) {
      super(base);
    }

    public void someMethod() {
        // notice how I can use "this" for Context
        // this works because this class has it's own Context just like an Activity or Service
        startActivity(this, SomeRealActivity.class);

        //would require context too
        File cacheDir = getCacheDir();
    }
}

ContextWrapper の JavaDoc

すべての呼び出しを別の Context に単に委譲する Context のプロキシ実装。元のコンテキストを変更せずに動作を変更するためにサブクラス化できます。

于 2016-12-13T08:29:11.067 に答える
4

メソッドには本体が必要だと思いますgetAppContext()

public static Context getAppContext()
   return MyApplication.context; 
于 2011-08-18T14:15:08.993 に答える
3

アプリ開発をより簡単にすることを目的とした、Vapor APIと呼ばれる Android 用の jQuery にインスパイアされたフレームワークをリリースしました。

中央の$ファサード クラスWeakReferenceは(Ethan Nicholas による素晴らしい Java ブログ投稿へのリンク) を現在のコンテキストに維持し、次のActivity呼び出しによって取得できます。

$.act()

は、ガベージ コレクションが元のオブジェクトを再利用することを妨げずに参照を維持するWeakReferenceため、メモリ リークの問題は発生しません。

$.act()もちろん、欠点は、 null を返す可能性があるというリスクを冒すことです。ただし、私はまだこのシナリオに出くわしていないので、言及する価値があるのはおそらく最小限のリスクです.

クラスVaporActivityとして使用していない場合は、コンテキストを手動で設定することもできます。Activity

$.act(Activity);

また、Vapor APIフレームワークの多くは、この保存されたコンテキストを本質的に使用します。つまり、フレームワークを使用することにした場合、それを自分で保存する必要がまったくないということです。詳細とサンプルについては、サイトをご覧ください。

それが役立つことを願っています:)

于 2013-02-26T10:50:21.870 に答える