Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/313.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 使用这种方式将上下文传递给非上下文类安全吗_Java_Android_Android Context - Fatal编程技术网

Java 使用这种方式将上下文传递给非上下文类安全吗

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

我读过几篇关于将上下文传递给适配器或其他内容的文章,我制作了一种用于获取应用程序上下文的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());