有很多问题涉及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原则?还是闻起来有气味?我只是无法决定。
每当将Context
实例传递给另一个类时,请想一想,
“这个班级实际上可能比我传给它的
Context
更长寿吗?”
如果答案是否定的,请不要担心。如果答案是肯定的,请考虑原因。
例如,View
s,如果正常使用,将永远不会比你的Activity
活得更久。一旦Activity
被垃圾收集,你的View
将收集垃圾,所以没有什么可担心的。
但是,单身人士会活得更久,而且会泄漏Context
。也就是说,当Activity
被认为是垃圾收集时,它不会,因为单身人士仍然有一个参考。
我想到了几个解决方案:
getApplicationContext()
作为单身人士。这种类型的Context
只要你的应用程序存在就会存在 - 因此只要你的单身人士生活。WeakReference
s。这样可以确保您不会对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;
}
看起来像整洁的代码。但为什么要经历所有这些复杂的动作只是为了传递背景?现在看来你正在传递一个不同的类(你的RememberMe类),这和传递上下文一样糟糕或好。所以我真的没有看到优势。