有没有一种方法可以在静态方法中获取当前的Context
实例?
我正在寻找这种方法,因为我讨厌每次更改时都要保存“Context”实例。
有没有一种方法可以在静态方法中获取当前的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 文件中的 标签中指定你的类的名称:
<application
...
android:name="com.example.App" >
...
</application>
你可以使用以下代码在任何静态方法中检索应用程序上下文:
public static void someMethod() {
Context context = App.getContext();
}
警告
在将类似上述内容添加到您的项目之前,您应该考虑文档中的建议:
通常不需要子类化 Application。 在大多数情况下,静态单例可以以更模块化的方式提供相同的功能。 如果您的单例需要全局上下文(例如注册广播接收器),则检索它的函数可以给出一个 Context,这个 Context 在首次构造单例时内部使用 Context.getApplicationContext()。
反射
还有另一种使用反射获取应用程序上下文的方法。在Android中,反射经常被轻视,我个人认为应该不要在生产中使用。
要检索应用程序上下文,我们必须调用一个隐藏类 (ActivityThread) 上的方法,该方法自 API 1 可用:
public static Application getApplicationUsingReflection() throws Exception {
return (Application) Class.forName("android.app.ActivityThread")
.getMethod("currentApplication").invoke(null, (Object[]) null);
}
还有一个隐藏的类(AppGlobals),它提供了一种静态的方式来获取应用程序上下文。它使用 ActivityThread
来获取上下文,因此以下方法与上面发布的方法实际上没有区别:
public static Application getApplicationUsingReflection() throws Exception {
return (Application) Class.forName("android.app.AppGlobals")
.getMethod("getInitialApplication").invoke(null, (Object[]) null);
}
开心编码!
并由Dianne Hackborn解释。注意:通常不需要子类化Application。在大多数情况下,静态单例可以以更模块化的方式提供相同的功能。如果您的单例需要全局上下文(例如注册广播接收器),请在调用单例的getInstance()方法时包含Context.getApplicationContext()作为上下文参数。
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();
如果有人感兴趣,可以在fwd博客阅读更详细的版本。
Application.onCreate()
中发布对 this
的静态引用来简化此过程,从而使接受的答案更好。 - Mark McKenna不,我认为没有。不幸的是,你只能从Activity
或其他Context
子类中调用getApplicationContext()
。此外,这个问题有些相关。
Kotlin之道:
清单文件:
<application android:name="MyApplication">
</application>
我的应用程序.kt
class MyApplication: Application() {
override fun onCreate() {
super.onCreate()
instance = this
}
companion object {
lateinit var instance: MyApplication
private set
}
}
您可以通过 MyApplication.instance
访问该属性。
以下是一种未记录在案的方式,可以在UI线程的任何地方获取一个Application(即一个Context)。它依赖于隐藏的静态方法ActivityThread.currentApplication()
。它至少应该适用于Android 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.Builder
创建一个 AlertDialog
,那么 Application
上下文将无法正常工作。我认为您需要当前 Activity
的上下文...
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()
如果你愿意使用RoboGuice,你可以将上下文注入到任何你想要的类中。以下是如何在RoboGuice 2.0 (beta 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) {
}
}
}
我曾经使用过这个:
ActivityThread at = ActivityThread.systemMain();
Context context = at.getSystemContext();
我曾经在获取系统服务时使用过这个有效的上下文,并且它很奏效。
但是,我只在framework/base的修改中使用过它,没有在Android应用程序中尝试过。
警告:您必须知道:在使用此上下文注册广播接收器时,它将无法正常工作,您将会看到以下错误消息:
java.lang.SecurityException:调用者包android未在ProcessRecord进程中运行