Java 使用这种方式将上下文传递给非上下文类安全吗
我读过几篇关于将上下文传递给适配器或其他内容的文章,我制作了一种用于获取应用程序上下文的contextholder:Java 使用这种方式将上下文传递给非上下文类安全吗,java,android,android-context,Java,Android,Android Context,我读过几篇关于将上下文传递给适配器或其他内容的文章,我制作了一种用于获取应用程序上下文的contextholder: import android.content.Context; public class ContextHolder { private static ContextHolder ourInstance = new ContextHolder(); private Context context; public static ContextHolder
import android.content.Context;
public class ContextHolder {
private static ContextHolder ourInstance = new ContextHolder();
private Context context;
public static ContextHolder getInstance() {
return ourInstance;
}
private ContextHolder() {
context = null;
}
public void setContext(Context context){
this.context = context;
}
public Context getApplicationContext(){
return context;
}
}
然后在MainActivity中,我创建ContextHolder对象并设置如下上下文:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ContextHolder contextHolder = ContextHolder.getInstance();
contextHolder.setContext(this.getApplicationContext());
}
在另一个类中,我需要使用contex:
ContextHolder contextHolder = ContextHolder.getInstance();
Resources resources = contextHolder.getApplicationContext().getResources();
问题是,我做得对吗?
它会导致内存泄漏或其他令人讨厌的事情吗
在MainActivity中,我正在创建ContextHolder
但是为什么呢?上下文的子类是否已存在:
java.lang.Object
↳ android.content.Context
↳ android.content.ContextWrapper
↳ android.view.ContextThemeWrapper
↳ android.app.Activity
因此,您可以只使用this
(或MainActivity.this
)。更不用说在显示的代码中放置holder对象的contextHolder
变量是局部范围的,仅在onCreate()
中可见
它会导致内存泄漏或其他令人讨厌的事情吗
我建议使用LeakCanary来捕获代码中的所有内存泄漏。见:
在另一个类中,我需要使用contex:
ContextHolder contextHolder = ContextHolder.getInstance();
Resources resources = contextHolder.getApplicationContext().getResources();
这一切都是不必要和过度设计的。如果只需要获取应用程序上下文,则子类application
class:
class MyApplication extends Application {
protected static Context mContext;
@Override
public void onCreate() {
super.onCreate();
mContext = this;
}
public static Context getAppContext() {
return mContext;
}
}
将其设置为清单中的应用程序类:
<application
android:name=".MyApplication"
...
我认为您保存对应用程序上下文的引用的方法很好。正如所说: 通常不需要对应用程序进行子类化。在大多数情况下,静态单例可以以更模块化的方式提供相同的功能 因此,仅仅为了获取对应用程序上下文的引用,不应该对应用程序类进行子类化 在您的情况下,您应该在第一个活动的
onCreate
方法中初始化单例,以便将this.getApplicationContext()
传递给要保留的单例。例如:
public class ContextHolder {
private static ContextHolder ourInstance;
private Context context;
public static ContextHolder getInstance() {
return ourInstance;
}
public static void init(Context context){
ourInstance = new ContextHolder(context);
}
private ContextHolder(Context context) {
this.context = context;
}
public Context getApplicationContext(){
return context;
}
}
在第一个活动的onCreate
中:
ContextHolder.init(getApplicationContext());
这将泄露上下文。不过,您可以在ContextHolder中使用WeakReference。应用程序上下文不是贯穿于整个应用程序生命周期吗?哦,是的。我的错。乍一看,我看到您使用了ApplicationContext。不要介意我的评论。虽然仅仅为上下文持有者扩展应用程序对象可能看起来很奇怪,但“通常不需要为应用程序子类化”并不是真的。显然,我的所有应用程序都不正常……无论如何,拥有ContextHolder模块也没有直接的好处(更不用说这种方法需要隐式初始化。拥有这个类基本上没有任何意义。@MarcinOrlowski你说得绝对正确。但是,这取决于OP选择最适合其目的的方法。在我看来,OP的方法(即singleton类)它比您的更好,因为它更兼容和分离职责原则。而且我认为这个类在运行时没有太多的重载。当然,我们可以忽略开销。我现在讨论的是实现。重点是在这种方法中,您必须隐式初始化单例。您要在哪里做呢-在MainActivity onCrea中te?好的,但是如果你转到另一个活动怎么办?你会再次初始化它吗?不。重复的代码,很容易认为它应该已经初始化。现在-如果你的应用程序被终止,然后用户稍后返回它,那么它将被重新创建。当要求上下文时,holder会返回什么?
null
,因为它根本不会被初始化->你们可以随时将应用程序扩展到init持有者:)@MarcinOrlowski我并没有考虑到这一点(Android杀死了应用程序)。现在,我应该承认你的方式比我的好。谢谢Marcin的这一点+1.
ContextHolder.init(getApplicationContext());