Androidで「コンテキスト」を取得する静的な方法?
-
18-09-2019 - |
質問
現在を取得する方法はありますか Context
静的メソッド内のインスタンス?
「Context」インスタンスが変更されるたびに保存するのが嫌なので、その方法を探しています。
解決
これを行います:
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()
を呼び出します。
他のヒント
アプリケーションコンテキストを取得する便利なメソッドを必要とするアプリケーションの大部分は、アプリケーションコンテキストを拡張する独自のクラスを作成します。 android.app.Application
.
ガイド
これを行うには、まずプロジェクト内に次のようなクラスを作成します。
import android.app.Application;
import android.content.Context;
public class App extends Application {
private static Application sApplication;
public static Application getApplication() {
return sApplication;
}
public static Context getContext() {
return getApplication().getApplicationContext();
}
@Override
public void onCreate() {
super.onCreate();
sApplication = this;
}
}
次に、AndroidManifest の AndroidManifest.xml タグにクラスの名前を指定する必要があります。
<application
...
android:name="com.example.App" >
...
</application>
次に、以下を使用して、任意の静的メソッドでアプリケーション コンテキストを取得できます。
public static void someMethod() {
Context context = App.getContext();
}
警告
上記のようなものをプロジェクトに追加する前に、ドキュメントに記載されている内容を考慮する必要があります。
通常、Application をサブクラス化する必要はありません。ほとんどの状況では、静的シングルトンはよりモジュール式の方法で同じ機能を提供できます。Singletonがグローバルコンテキスト(たとえば、ブロードキャストレシーバーを登録するため)が必要な場合、それを取得する関数は、Singletonを最初に構築するときにContext.GetApplicationContext()を内部的に使用するコンテキストを指定できます。
反射
リフレクションを使用してアプリケーション コンテキストを取得する別の方法もあります。リフレクションは Android では軽視されることが多いため、個人的にはこれを運用環境で使用すべきではないと考えています。
アプリケーションコンテキストを取得するには、非表示クラスのメソッドを呼び出す必要があります(アクティビティスレッド) API 1 から利用可能になっています。
public static Application getApplicationUsingReflection() throws Exception {
return (Application) Class.forName("android.app.ActivityThread")
.getMethod("currentApplication").invoke(null, (Object[]) null);
}
もう 1 つ隠しクラスがあります (アプリグローバル) 静的な方法でアプリケーション コンテキストを取得する方法を提供します。を使用してコンテキストを取得します ActivityThread
したがって、次の方法と上で投稿した方法の間に実際には違いはありません。
public static Application getApplicationUsingReflection() throws Exception {
return (Application) Class.forName("android.app.AppGlobals")
.getMethod("getInitialApplication").invoke(null, (Object[]) null);
}
コーディングを楽しんでください!
私たちは、アプリケーション・コンテキストを取得して話をしていると仮定すると、私はそれを実装しました。その後、何が起こったのか、それは、このような方法で取得したコンテキストは常に非nullになりますという保証はありませんということです。あなたは時間の遅延することができないという、ヘルパーを初期化、またはリソースを取得したいので、あなたがそれを必要とする時には、それが通常です。 nullの場合を扱うことはあなたを助けにはなりません。 ドキュメントに記載されているようにだから私は/ <、私は基本的にAndroidのアーキテクチャと戦った理解しましたA>
注:アプリケーションをサブクラス化する必要は通常ありません。ほとんどの状況では、静的なシングルトンは、よりモジュラーな方法で同じ機能を提供することができます。あなたのシングルトンは、グローバルコンテキストを必要とする場合(例えば放送受信機を登録する)、あなたのシングルトンののgetInstance()メソッドを呼び出すときにコンテキスト引数としてContext.getApplicationContextを()が含まれます。
とダイアンHackborn の
により説明アプリケーションは、あなたがから派生することができるものとして存在する唯一の理由は、事前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で、より詳細なバージョンを読むことができますブログで
いいえ、私はないと思います。残念ながら、あなたはgetApplicationContext()
またはActivity
の他のサブクラスの1からContext
を呼び出して立ち往生しています。また、このの質問は多少関係してます。
ここでアプリケーションを取得するための文書化されていないの方法がありますどこUIスレッド内からの(コンテキストです)。それは隠された静的メソッドActivityThread.currentApplication()
に依存しています。それは、少なくともアンドロイドの4.x上で動作するはずです。
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
}
この方法は、例えば、nullを返すすることが可能であることに注意してくださいあなたは、UIスレッドの外でメソッドを呼び出す、またはアプリケーションをスレッドにバインドされていないときます。
あなたがアプリケーション・コードを変更することができるかどう @RohitGhatol ののソリューションを使用することがまだ良いです。
それはあなたのためのコンテキストを使用しているかに依存します。私は、そのメソッドに少なくとも一つの欠点を考えることができます:
あなたはAlertDialog
とAlertDialog.Builder
を作成しようとしている場合は、、Application
コンテキストは動作しません。私はあなたが現在Activity
のコンテキストを必要とすると信じて...
、あなたはどのに注入コンテキストを持つことができますあなたがしたいクラス。ここで
(この記事の執筆時点ではベータ4)RoboGuice 2.0でそれを行う方法の小さなサンプルです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) {
}
}
}
私はいくつかの点で、これを使用しました。
ActivityThread at = ActivityThread.systemMain();
Context context = at.getSystemContext();
これは私がシステムサービスを得ることで使用して働いていた有効なコンテキストである。
しかし、私は唯一のフレームワーク/塩基修飾でそれを使用してAndroidアプリケーションでそれをしようとしなかった。
A をあなたが知らなければならないことの警告:この文脈で放送受信機に登録するときは、それが動作しません、あなたが取得します。
java.lang.SecurityException:与えられた発信者パッケージAndroidがプロセスProcessRecordで実行されていない
Kotlin の方法:
マニフェスト:
<application android:name="MyApplication">
</application>
MyApplication.kt
class MyApplication: Application() {
override fun onCreate() {
super.onCreate()
instance = this
}
companion object {
lateinit var instance: MyApplication
private set
}
}
その後、MyApplication.instance 経由でプロパティにアクセスできるようになります。
あなたがマニフェストファイルを変更したくない場合は、手動で初期活性に静的変数のコンテキストを保存することができます:
public class App {
private static Context context;
public static void setContext(Context cntxt) {
context = cntxt;
}
public static Context getContext() {
return context;
}
}
そして、あなたの活動(または活動)が起動したときだけコンテキストを設定します:
// MainActivity
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Set Context
App.setContext(getApplicationContext());
// Other stuff
}
<時間>
注:すべての他の回答のように、これは潜在的なメモリリークです。
。Kotlin
open class MyApp : Application() {
override fun onCreate() {
super.onCreate()
mInstance = this
}
companion object {
lateinit var mInstance: MyApp
fun getContext(): Context? {
return mInstance.applicationContext
}
}
}
と
のようなコンテキストを取得MyApp.mInstance
または
MyApp.getContext()
私はあなたがgetAppContext()
メソッドの体が必要だと思います
public static Context getAppContext()
return MyApplication.context;
あなたは以下を使用することができます:
MainActivity.this.getApplicationContext();
MainActivity.javaます:
...
public class MainActivity ... {
static MainActivity ma;
...
public void onCreate(Bundle b) {
super...
ma=this;
...
他のクラスます:
public ...
public ANY_METHOD... {
Context c = MainActivity.ma.getApplicationContext();
によると、このソース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
その単純委譲する別のコンテキストへの呼び出しのすべてのコンテキストの実装のプロキシ。元のコンテキストを変更せずに動作を変更するためにサブクラス化することができます。
これを支援するために、Singleton 設計パターンのバリエーションを使用します。
import android.app.Activity;
import android.content.Context;
public class ApplicationContextSingleton {
private static Activity gContext;
public static void setContext( Activity activity) {
gContext = activity;
}
public static Activity getActivity() {
return gContext;
}
public static Context getContext() {
return gContext;
}
}
それから私は電話します ApplicationContextSingleton.setContext( this );
私の中で activity.onCreate() そして ApplicationContextSingleton.setContext( null );
で onDestroy();
私は、Android向けのjQueryをほうふつさせるフレームワークをリリースし、アプリケーションの開発をより簡単にすることを目指して蒸気API で呼ばれます。
//ブログ:は、中央のの$
ファサードクラスには、<のhref = "HTTPを維持します。 java.net/blog/2006/05/04/understanding-weak-references」のrelは= 『nofollowを』> WeakReference
の(イーサンニコラスによって、このことについて素晴らしいのJavaのブログ記事へのリンク)をすることができます現在Activity
コンテキストへ呼び出すことによって取得ます:
$.act()
WeakReference
は、元のオブジェクトを再利用ガベージコレクションを妨げることなく参照を保持し、あなたはメモリリークの問題を持つべきではありません。
もちろんの欠点は、あなたが$.act()
はnullを返す可能性というリスクを実行することです。それは、おそらく言及する価値だけで最小限のリスクですので、私は、まだしかし、このシナリオに遭遇していない。
VaporActivity
クラスとして Activity
に使用していない場合は、また、手動でコンテキストを設定することができます。
$.act(Activity);
また、蒸気API のフレームワークは、本質的に、この保存されたコンテキストを使用して、あなたがそれを格納する必要はありません意味可能性がありますすべてであなたがフレームワークを使用することを決定した場合は、自分自身。詳細情報およびサンプルのためのサイトをチェックします。
私はそれが役に立てば幸い:)
何らかの理由で、あなたは、おそらくいくつかの工場やヘルパークラスのための任意のクラスのアプリケーションコンテキストだけでなく、これらの拡張アプリケーション/活動を、必要な場合。あなたは、あなたのアプリに次のシングルトンを追加することができます。
public class GlobalAppContextSingleton {
private static GlobalAppContextSingleton mInstance;
private Context context;
public static GlobalAppContextSingleton getInstance() {
if (mInstance == null) mInstance = getSync();
return mInstance;
}
private static synchronized GlobalAppContextSingleton getSync() {
if (mInstance == null) mInstance =
new GlobalAppContextSingleton();
return mInstance;
}
public void initialize(Context context) {
this.context = context;
}
public Context getApplicationContext() {
return context;
}
}
そして
を使用してアプリケーションクラスののonCreateでそれを初期化しますGlobalAppContextSingleton.getInstance().initialize(this);
タグ呼び出すことにより、どこでもそれを使用します
GlobalAppContextSingleton.getInstance().getApplicationContext()
しかし私は何もなく、アプリケーションのコンテキストにこの方法をお勧めしません。それはメモリリークを引き起こす可能性がある。
のRohitの答えが正しいようです。しかし、AndroidStudioの「インスタントファイル名を指定して実行」は私の知る限り、あなたのコードでstatic Context
属性を持っていないに依存することに注意してます。
そのメモリリークの原因となるので、だから私は受け入れ答えを変更し、これは私が
...思い付いたものですのAndroidManifest.xml
<application android:name="com.xyz.MyApplication">
...
</application>
MyApplication.java
public class MyBakingAppContext extends Application {
private static Object mContext;
public void onCreate() {
super.onCreate();
mContext = getApplicationContext();
}
public static Context getAppContext() {
return (Context)mContext;
}
}
私が実際にやった、オブジェクトにコンテキストを割り当て、(文脈にキャスト)コンテキストとしてオブジェクトを返します。それは助けを願っています。
Kotlinで、まだDo not place Android context classes in static fields; this is a memory leak (and also breaks Instant Run)
を警告が生成コンパニオンオブジェクトにコンテキスト/アプリケーションコンテキストを置く
またはあなたがこのような何かを使用する場合:
companion object {
lateinit var instance: MyApp
}
Applicationクラスとその子孫がコンテキストであるため、これは、単純にメモリリークを検出しないように糸くずをだましています、アプリケーションインスタンスは、まだ、メモリリークを生成することができます。
また、あなたはあなたのアプリケーションのコンテキストを得るのを助けるために機能的なインタフェースまたは機能的特性を使用することができます。
単にオブジェクトクラスを作成します:
object CoreHelper {
lateinit var contextGetter: () -> Context
}
またはあなたがNULL可能タイプを使用して、より安全に使用することができます:
object CoreHelper {
var contextGetter: (() -> Context)? = null
}
、アプリのクラスでは、この行を追加します:
class MyApp: Application() {
override fun onCreate() {
super.onCreate()
CoreHelper.contextGetter = {
this
}
}
}
とマニフェスト宣言でアプリ名が. MyApp
する
<application
android:name=".MyApp"
あなたがコンテキストを取得したい場合は、単純に呼び出します:
CoreHelper.contextGetter()
// or if you use the nullable version
CoreHelper.contextGetter?.invoke()
それに役立つことを願っています。