【问题标题】:Passing `Context` everywhere seems messy - create classes to handle different interactions with context?到处传递“上下文”似乎很乱——创建类来处理与上下文的不同交互?
【发布时间】:2014-08-13 09:03:19
【问题描述】:

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

我在想另一种方法是创建充当上下文代理的类,我将其传递给它,将上下文功能的子集定义为一种接口(不是语言 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 原则与之相悖?或者它修复的气味?我只是无法决定。

【问题讨论】:

  • 传递StateStorerContext 有什么区别?在这两种情况下,您将Context(间接)传递给的实例都引用了Context
  • 真棒的问题,我多年来一直在想。
  • Context 对象似乎做了这么多,我总是发现自己想知道为什么一个对象需要一个上下文,并且必须进去看看。也许它只是更明确。出于同样的原因,它也可能有助于避免传递错误类型的上下文

标签: java android android-context


【解决方案1】:

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

这个类有没有可能比我传给它的 Context 寿命更长?

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

Views 例如,如果正常使用,它的寿命永远不会超过你的Activity。只要Activity 被垃圾收集,你的View 就会被垃圾收集,所以没什么好担心的。

然而,单身人士确实寿命更长,并且泄露Context。也就是说,当Activity 应该被垃圾回收时,它不会被回收,因为单例仍然有对它的引用。

想到了几个解决方案:

  • getApplicationContext() 用于单例。这种类型的 Context 与您的应用程序一样存在 - 因此只要您的单例存在。
  • 使用WeakReferences。这可确保您不会保留对 Context 的活动引用,并避免泄漏。但是,您需要补偿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;
}

【讨论】:

    【解决方案2】:

    看起来像整洁的代码。但是,为什么要通过所有这些复杂的动作来传递上下文呢?在我看来,现在您正在传递不同的课程(您的 RememberMe 课程),这与传递上下文一样好或坏。所以我并没有真正看到优势。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-02-04
      • 2019-06-02
      • 1970-01-01
      • 2011-05-07
      • 1970-01-01
      相关资源
      最近更新 更多