有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

到处传递“Context”的java看起来很混乱,是否创建类来处理与上下文的不同交互?

有大量的问题涉及Context,使用哪种上下文,以及如何存储它,等等。但是每次我将它传递给对象,或者创建一个提供对它的访问的静态或单例时,我都会感到脏兮兮的。我不确定我闻到了什么味道,但它确实有味道

我在想另一种方法是创建充当上下文代理的类,而我将其传递给上下文,将上下文特性的子集定义为一种接口(而不是languageinterface关键字)

备选方案的一个示例(为便于阅读而省略代码):

// 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原则的吗?或者它能修复的气味?我就是不能决定


共 (2) 个答案

  1. # 1 楼答案

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

  2. # 2 楼答案

    每当将Context实例传递给另一个类时,请思考

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

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

    例如View在正常使用时,它的寿命永远不会超过你的Activity。一旦Activity被收集到垃圾,你的View就会被收集到垃圾,所以没什么好担心的

    然而,确实活得更长,泄漏Context。也就是说,当Activity应该被垃圾收集时,它将不会被垃圾收集,因为singleton仍然有对它的引用

    我想到了几个解决方案:

    • 对单例使用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;
    }