是否有一种方法来获得静态方法内的当前上下文实例?
我正在寻找这种方式,因为我讨厌保存'Context'实例每次它改变。
是否有一种方法来获得静态方法内的当前上下文实例?
我正在寻找这种方式,因为我讨厌保存'Context'实例每次它改变。
当前回答
如果你出于某种原因想在任何类中都有Application上下文,而不仅仅是那些扩展应用程序/活动,也许是一些工厂类或帮助类。你可以将以下单例添加到你的应用程序中。
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 with中初始化它
GlobalAppContextSingleton.getInstance().initialize(this);
在任何地方通过调用使用它
GlobalAppContextSingleton.getInstance().getApplicationContext()
但是,除了应用程序上下文之外,我不推荐使用这种方法。因为它会导致内存泄漏。
其他回答
如果你出于某种原因想在任何类中都有Application上下文,而不仅仅是那些扩展应用程序/活动,也许是一些工厂类或帮助类。你可以将以下单例添加到你的应用程序中。
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 with中初始化它
GlobalAppContextSingleton.getInstance().initialize(this);
在任何地方通过调用使用它
GlobalAppContextSingleton.getInstance().getApplicationContext()
但是,除了应用程序上下文之外,我不推荐使用这种方法。因为它会导致内存泄漏。
如今,拥有上下文的正确方法是使用依赖注入。 例如,可以使用Hilt在任何需要的地方注入上下文。假设一个人需要某个数据库管理器中的上下文,那么这可以通过以下方式解决:
在Gradle中添加刀柄:
implementation "com.google.dagger:hilt-android:2.35"
kapt "com.google.dagger:hilt-android-compiler:2.35"
用@HiltAndroidApp注解定义Application类(例如,让它注入数据库管理器):
@HiltAndroidApp
class MyApplication : Application() {
@Inject
lateinit var dbManager: DBManager
override fun onCreate() {
super.onCreate()
dbManager.initDB()
}
}
定义数据库管理器(以@Singleton为例):
@Singleton
class DBManager @Inject constructor(
@ApplicationContext private val context: Context
) {
fun initDB() {
// context is avaiable
databaseInit(context)
}
}
就是这样。DBManager可以以正确的方式访问上下文,没有内存泄漏。
如果你不想修改清单文件,你可以手动将上下文存储在初始活动的静态变量中:
public class App {
private static Context context;
public static void setContext(Context cntxt) {
context = cntxt;
}
public static Context getContext() {
return context;
}
}
当你的activity(或多个activity)开始时,只需设置上下文:
// MainActivity
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Set Context
App.setContext(getApplicationContext());
// Other stuff
}
注意:与所有其他答案一样,这是一个潜在的内存泄漏。
这取决于您使用上下文的目的。我认为这种方法至少有一个缺点:
如果您正在尝试使用AlertDialog创建AlertDialog。Builder,应用程序上下文将无法工作。我相信你需要了解当前活动的背景……
下面是一种从UI线程中的任何地方获取应用程序(它是一个上下文)的未记录的方法。它依赖于隐藏的静态方法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的解决方案仍然更好。