java - 在任何地方传递 `Context` 似乎都很困惑 - 创建类来处理与上下文的不同交互?

标签 java android android-context

有很多问题涉及Context,使用哪个上下文,以及如何存储它等等。但是每次我将它传递给一个对象,或者创建一个静态的时候我都觉得很脏或提供对它的访问的单例。我不确定我闻到的是什么气味,但肯定是闻起来的。

我在想另一种方法是创建充当上下文代理的类,我将其传递给它,它将上下文功能的子集定义为一种接口(interface)(不是语言 interface 关键字)。

一个替代示例(为了便于阅读而省略了代码):

// in activity.onCreate():

    StateStorer ss = new StateStorer (getApplicationContext());
    RememberMe obj = new RememberMe(ss);
    ss.restore();

// in activity.onDestroy()

    ss.save();

// the "proxy"
class StateStorer {
    List<StateStorerListener> listeners;
    Context mContext;
    public StateStorer(Context context){
        mContext = context;
    }
    public SharedPreferences getSharedPreferences(String tag){
        return mContext.getSharedPreferences(tag, 0);
    }
    public save(){
        // tell listeners to save
    }
    public restore(){
        // tell listeners to restore
    }
}

// an example class that needs to save state

class RememberMe {
    public String TAG = "RememberMe";
    public StateStorer mSs;
    public RememberMe (StateStorer ss){
        mSs = ss;
        ss.addListener(this)
    }
    // this class would implement the StateStorer's listener interface,
    // and when the StateStorer tells it to save or restore, it will use the
    // StateStorer's methods to access the SharedPreferences object
    public void onRestore(){
        SharedPreferences sp = sSs.getSharedPreferences(TAG);
        // restore from prefs here
    }
}

这是否违反了任何 OOP 原则?或者闻起来它修复了?我就是不能决定。

最佳答案

每当将 Context 实例传递给另一个类时,想想,

"Is it possible that this class will actually live longer than the Context I'm passing to it?"

如果答案是否定的,请不要担心。如果答案是肯定的,想想为什么

例如,

View 在正常使用时,永远不会比您的 Activity 生命周期更长。一旦 Activity 被垃圾回收,您的 View 就会被垃圾回收,所以没有什么可担心的。

然而,单例确实活得更久,而且泄漏上下文。也就是说,当 Activity 应该被垃圾回收时,它不会被回收,因为单例仍然有对它的引用。

我想到了几个解决方案:

  • 对单例使用getApplicationContext()。只要您的应用程序存在,这种类型的 Context 就会存在 - 因此只要您的单例存在。
  • 使用弱引用。这确保您不会保留对您的 Context 的 Activity 引用,并避免泄漏。但是,您需要补偿 Context 可能无效的情况。

显然,您需要了解垃圾回收的基础知识。 Here's an article about that .


至于您提供的示例代码,我认为传递此实例与传递实际的 Context 没有区别。在这两种情况下,您都持有对 Context 的引用。事实上,StateStorer 类似乎是一个单例,并且 - 就像您所做的那样 - 应该与 ApplicationContext 一起提供。

您还会经常看到,当提供 Context 时,单例会自行调用 getApplicationContext() 以避免此类错误:

public static MySingleton getInstance(final Context context) {
    if(sInstance == null) {
        sInstance = new MySingleton(context.getApplicationContext());
    }

    return sInstance;
}

关于java - 在任何地方传递 `Context` 似乎都很困惑 - 创建类来处理与上下文的不同交互?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25282171/

相关文章:

android - 为什么 Activity.getPackageManager() 会返回 null

android - Android 中的服务上下文和应用程序上下文之间有区别吗?

java - 按下按键后绘制的对象不会清除先前的矩形

android - 在项目 gradle 中设置构建 :gradle:3. 0.1 或最新版本时出现 AAPT2 错误

java - Android APK 中的引用类

java - 为什么我得到 java.lang.ArithmeticException : divide by zero

Android Data Binding疑惑

java - 为什么我在创建新的 Android 项目时遇到渲染错误?

仅当通过文件接收(非用户)输入时才执行的 Java 程序

java - 递归搜索数组