首页 文章

使用上下文而没有任何静态引用

提问于
浏览
3

我试图从Singleton类访问应用程序资源(字符串资源是特定的) . 作为Singleton,这个类不能保存对Context对象的任何引用(以防止内存泄漏) . 当我在网上寻找其他实现时,我遇到了这两个实现:

  • 在Application类中创建静态上下文,并在整个应用程序中使用它 .

  • 将上下文作为参数传递给需要它的方法 .

我不想使用第一个,因为它也使用对Context对象的静态引用 . 我明白在android的Application类中静态地使用它是可以的,但它仍然看起来像一个黑客 .

第二个实现是无用的,因为我没有任何上下文实例,我可以传递给单例的someOtherMethod .

因此,当我初始化单例实例时,我提出了以下实现,其中我使用Singleton抽象来覆盖其上下文需要方法(例如,在下面的代码中为 getString(int resId) ) .

我很想知道这是否会导致任何内存泄漏?

我在哪里与这种方法混淆:

  • Overridden 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()
    }

    }

2 回答

  • 0

    你的方法确实有内存泄漏 . 传递到 getInstance 的第一个上下文永远不会被垃圾收集,因为您的匿名类持有对它的引用 . (并且有一个匿名类的静态引用) . 例如,如果您调用 getInstance(Activity) ,该活动将保留在内存中,直到该进程被终止!

    幸运的是,有一个非常简单的解决办法来摆脱内存泄漏 . 您可以安全地保留应用程序上下文( context.getApplicationContext ),这基本上是应用程序生命周期的单例上下文 .

    public static SingletonClass getInstance(Context c) {
        if (sInstance == null) {
            sInstance = new SingletonClass(c.getApplicationContext());
        }
        return sInstance;
    }
    
  • 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;
      }
    }
    

    第二种情况可以参考完成活动,所以我不建议 .

相关问题