静态对象(如单身人士)可以泄漏非静态上下文吗?为什么?

时间:2017-01-08 16:20:56

标签: java android memory-leaks

这可能听起来像一个愚蠢的问题,但我在单个和POJO的两个设计模型之间翻转访问共享Prefs,我想防止任何mem。在背景方面泄漏。

我知道静态对象被分配给堆,但是对于单个设计,保持不静态,并声明自己的静态实例并实例化它,如果这个实例传递上下文来做某种类型的方法,

  • 可以泄露这种情况吗?
  • 如果不是,为什么不,如果是,为什么以及如何解决?

这是我创建的当前单身人士设计

public class UserSettings {
  private UserSettings settings = new UserSettings();

  private UserSettings() {
    }

    public static UserSettings getInstance() {
        return settings;
    }

    private SharedPreferences getPrefs(Context context) {
        return context.getSharedPreferences(
                USER_SETTINGS_FILE,
                Context.MODE_PRIVATE
        );
    }

    private SharedPreferences.Editor getEditor(Context context) {
        return context.getSharedPreferences(
                USER_SETTINGS_FILE,
                Context.MODE_PRIVATE
        ).edit();
    }

    public Object get(Context context,int item) {
        SharedPreferences sp = getPrefs(context);
        switch (item) {
            case TIMING:
                return sp.getInt(KEY_USER_TIMING,60);
            case NAME:
                return sp.getString(KEY_USER_NAME,"Stranger");
            // .. etc
            default:
                return 0;
        }
    }

    public void update(Context context,int setting, Object updateValue) throws ClassCastException {
        SharedPreferences.Editor sp = getPrefs(context).edit();
        switch (setting) {
            case TIMING:
                if (Integer.class.isInstance(updateValue))
                    sp.putInt(KEY_USER_TIMING,(int)updateValue).commit();
                else
                    throw new ClassCastException("User Time must be int");
                break;
            case NAME:
                if (String.class.isInstance(updateValue))
                    sp.putString(KEY_USER_NAME,(String)updateValue).commit();
                else
                    throw new ClassCastException("User Name must be String");
                break;
           // .... etc
            default:
                break;
        }
    }

}

1 个答案:

答案 0 :(得分:1)

如果您没有创建对上下文的引用,而是将其传递给每个方法调用,则它不会泄漏,因为它没有被保留。如果您在其生命周期之外存储了对它的引用,那么您只会泄漏上下文。例如,如果我存储使用Activity上下文静态初始化单例。即使活动消失,上下文对象也不会被最终确定,因为它仍然在某个地方引用它。

然而,有几种设计模式可以完美地实现这一点。我通常使用Dagger

这不会导致上下文泄漏,因为Singleton SharedPreferencesHelper的生命周期与应用程序的生命周期相关联,并且它使用应用程序上下文。

CustomApplication.java

private static ObjectGraph staticRefToObjectGraph;

@Override
public void onCreate() {
    super.onCreate();

    staticRefToObjectGraph = ObjectGraph.create(new MyModule(this));
}

public static void inject(Object obj) {
    staticRefToObjectGraph.inject(obj);
}

MyModule.java

public MyModule(Context applicationContext) {
    SharedPreferences prefs = PreferenceManager.getSharedPreferences(applicationContext);
    prefsHelper = new SharedPreferencesHelper(prefs);
}

@Provides
@Singleton
public SharedPreferencesHelper providePrefsHelper() {
    return prefsHelper;
}

MyActivity.java

@Inject SharedPreferencesHelper prefsHelper

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    MyApplication.performInjection(this);
}