传递`Context`到处都是混乱的 - 创建类来处理与上下文的不同交互?

问题描述 投票:7回答:2

有很多问题涉及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原则?还是闻起来有气味?我只是无法决定。

java android android-context
2个回答
3
投票

每当将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;
}

0
投票

看起来像整洁的代码。但为什么要经历所有这些复杂的动作只是为了传递背景?现在看来你正在传递一个不同的类(你的RememberMe类),这和传递上下文一样糟糕或好。所以我真的没有看到优势。

© www.soinside.com 2019 - 2024. All rights reserved.