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

Is it safe to use this way to pass context to non-context classes

我已经阅读了几篇关于将上下文传递给适配器或其他东西的文章,并且我制作了某种上下文持有者来获取应用程序上下文:

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());
    }

在其他一些 class 中,我需要使用 contex:

ContextHolder contextHolder = ContextHolder.getInstance();
Resources resources = contextHolder.getApplicationContext().getResources();

问题是,我做的对吗? 它会导致内存泄漏或其他讨厌的东西吗?

in MainActivity i`m creating ContextHolder

但是为了什么? Activity 已经是上下文的子class:

java.lang.Object
  ↳ android.content.Context
    ↳ android.content.ContextWrapper
      ↳ android.view.ContextThemeWrapper
        ↳ android.app.Activity

所以您可以只使用 this(或 MainActivity.this)。更不用说 contextHolder 变量,你把你的 holder 对象放在显示的代码中是局部范围的,并且只在 onCreate() 中可见。

Can it cause memory leaks or other nasty stuff?

我建议使用 LeakCanary 来捕获代码中的所有内存泄漏。参见:https://github.com/square/leakcanary

In some other class, where i need to use contex:

ContextHolder contextHolder = ContextHolder.getInstance();
Resources resources = contextHolder.getApplicationContext().getResources();

这都是不必要的,而且设计过度了。如果你只需要获取应用程序上下文,subclass Application class:

class MyApplication extends Application {
    protected static Context mContext;

    @Override
    public void onCreate() {
       super.onCreate();

       mContext = this;
    }

    public static Context getAppContext() {
       return mContext;
    }
}

在清单中将其设置为您的应用程序 class:

<application
    android:name=".MyApplication"
    ...

然后,每当您需要无法通过其他方式获得的上下文时,只需调用:

MyApplication.getAppContext();

我认为您保存对应用程序上下文的引用的方法很好。正如 docs 所说:

There is normally no need to subclass Application. In most situation, static singletons can provide the same functionality in a more modular way.

因此,仅仅为了获取对您的应用程序上下文的引用,您不应该 class 应用程序 class。

在您的情况下,您应该在第一个 activity 的 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;
    }
}

在你的第一个 Activity 中 onCreate :

ContextHolder.init(getApplicationContext());