我正在尝试从Singleton类访问应用程序资源(字符串资源是特定的)。作为Singleton,这个类不能保存对Context对象的任何引用(以防止内存泄漏)。当我在网上寻找其他实现时,我遇到了这两个实现:
我不想使用第一个,因为它也使用对Context对象的静态引用。我知道在Android的Application类中静态地使用它是可以的,但它仍然看起来像是黑客。
第二个实现是没用的,因为我没有任何上下文实例,我可以传递给单例的someOtherMethod。
所以当我初始化单例实例时,我想出了以下实现,其中我使用我的Singleton抽象来覆盖其上下文需要方法(对于前面的代码中的例如getString(int resId)
)。
我很想知道这是否会导致任何内存泄漏?
我在哪里与这种方法混淆:
- >重写getString
中对上下文的引用是最终的。我不确定这是否会导致内存泄漏。
public abstract class SingletonClass{
.
.
.
private static SingletonClass sInstance;
private SingletonClass(Context paramContext) {
// constructor code
}
public static SingletonClass getInstance(final Context context) {
if (sInstance == null) {
sInstance = new SingletonClass(context){
@Override
public String getString(int resId) {
return context.getString(resId);
}
};
}
return sInstance;
}
public abstract String getString(int resId);
.
.
.
private void someOtherMethod(){
//uses above getString()
}
}
答案 0 :(得分:0)
您的方法确实存在内存泄漏。传递给getInstance
的第一个上下文永远不会被垃圾收集,因为您的匿名类包含对它的引用。 (并且有一个匿名类的静态引用)。例如,如果你打电话给getInstance(Activity)
,该活动将保留在内存中,直到该进程被终止!
幸运的是,有一个非常简单的解决办法来摆脱内存泄漏。您可以安全地保留应用程序上下文(context.getApplicationContext
),这基本上是应用程序生命周期的单例上下文。
public static SingletonClass getInstance(Context c) {
if (sInstance == null) {
sInstance = new SingletonClass(c.getApplicationContext());
}
return sInstance;
}
答案 1 :(得分:0)
您可以依赖于活动生命周期,并要求活动在onResume方法中传递对单个对象的引用,并在onPause中清除它。
protected void onResume() {
super.onResume();
Singleton.getInstance().onResume(this);
}
protected void onPause() {
super.onResume();
Singleton.getInstance().onPause();
}
此外,您可以刷新Context
的实例并将其保存在WeakReference
中:
class Singleton {
private WeakReference<Context> mContext;
private boolean hasContext() {
return mContext != null && mContext.get() != null;
}
public static Singleton getInstance(Context c) {
//do your singleton lazy
if (!sInstance.hasInstance()) {
sInstance.mContext = new WeakReference<>(c);
}
return sInstance;
}
}
第二种情况可以引用完成活动,所以我不建议。