Android 使用上下文而不使用任何静态引用
我试图从单例类访问应用程序资源(具体来说是字符串资源)。由于是单例的,这个类不能保存对上下文对象的任何引用(以防止内存泄漏)。当我在网上寻找其他实现时,我遇到了以下两种实现:Android 使用上下文而不使用任何静态引用,android,design-patterns,memory-leaks,singleton,Android,Design Patterns,Memory Leaks,Singleton,我试图从单例类访问应用程序资源(具体来说是字符串资源)。由于是单例的,这个类不能保存对上下文对象的任何引用(以防止内存泄漏)。当我在网上寻找其他实现时,我遇到了以下两种实现: 在应用程序类中创建静态上下文,并在整个应用程序中使用它 将上下文作为参数传递给需要它的方法 我不想使用First,因为它还使用对上下文对象的静态引用。我知道在android的应用程序类中静态地使用它是可以的,但它看起来仍然像一个黑客 第二个实现是无用的,因为我没有任何上下文实例可以传递给singleton的SomeOthe
getString(intresid)
)
我很想知道这是否会导致内存泄漏
我对这种方法有何误解:
-->重写的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()
}
}
您的方法确实存在内存泄漏。传递到
getInstance
的第一个上下文永远不会被垃圾收集,因为匿名类持有对它的引用。(并且存在对匿名类的静态引用)。e、 例如,如果调用getInstance(Activity)
,该活动将保留在内存中,直到进程被终止
幸运的是,有一个非常简单的修复方法可以消除内存泄漏。您可以安全地保留应用程序上下文(context.getApplicationContext
),它基本上是应用程序生命周期中的单例上下文
public static SingletonClass getInstance(Context c) {
if (sInstance == null) {
sInstance = new SingletonClass(c.getApplicationContext());
}
return sInstance;
}
您可以依赖于活动生命周期,并要求活动在onResume方法中传递对singleton对象的引用,并在onPause中清除它
protected void onResume() {
super.onResume();
Singleton.getInstance().onResume(this);
}
protected void onPause() {
super.onResume();
Singleton.getInstance().onPause();
}
此外,您还可以刷新上下文的实例
,并将其保存在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;
}
}
类单例{
私有WeakReference mContext;
私有布尔hasContext(){
返回mContext!=null&&mContext.get()!=null;
}
公共静态单例getInstance(上下文c){
//你的单身汉懒惰吗
如果(!sInstance.hasInstance()){
sInstance.mContext=新的WeakReference(c);
}
回归承诺;
}
}
第二种情况可能会引用finishing activity,因此我不建议这样做。您可以分享一下如何使用这些字符串,更具体地说,为什么在使用它们时没有
上下文
?在大多数情况下,Activity/Service/BroadcastReceiver/SQLiteOpenHelper/等都会提供上下文,这使得您的单身汉变得有些不必要。我正在开发一款android游戏,并在其中使用Google Play游戏服务。我认为singleton是因为我需要在整个应用程序中保持一个GoogleAppClient。singleton的功能是做一些异步的事情。如果上下文
突然变为null
,它会抛出一个错误,不是吗?@AnkitMundada如果您的上下文变为null,那么您就与上下文无关了。如果资源的上下文为null,您可以只返回null。我的意思是,在您的第一个方法中,当我在onResume()
中清理上下文时,但如果它仍然由单例的异步调用使用,它不会引发异常吗?如果异步进程仍在使用上下文,为什么要说“您不再与上下文有任何关系?”那么请使用锁定以避免异常。处理异步代码是您的责任,这不是常见的情况。