Android:静态字段和内存泄漏

前端之家收集整理的这篇文章主要介绍了Android:静态字段和内存泄漏前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我一直在研究在创建视图时防止上下文/活动内存泄漏的最佳实践,对于类中的静态字段,我似乎无法找到关于什么是或不允许的明确答案.

假设我有一个这样的代码

public class MyOuterClass extends Activity{
   private MyInnerClass;
   MyInnerClass = (MyInnerClass) findViewById(<XML call here>);
   MyInnerClass.myXInt = 3;

   // onCreate(),onResume(),etc.

   public static class MyInnerClass extends SurfaceView implements Runnable{
      // Safe variables?
      private static int myXInt,myYInt;
      private static boolean myBoolean;
      // Potentially safe?
      private static Canvas myCanvas;
      // Definitely bad.
      private static Context myContext;

      public MyInnerClass(Context context){
         myContext = context;        // This is bad.
      }
   }
}

我对JVM实际考虑了MyInnerClass的ClassLoader有点困惑.在技​​术上,由于它是一个SurfaceView对象,似乎一旦应用程序一次实例化了MyInnerClass(这在View被首先膨胀时发生),静态变量就应该始终存在,然后一直保留在应用程序本身被终止之前.如果是这样,那么什么可以防止Bitmap和Canvas对象保持打开状态并填满堆?

我曾经看到的唯一的声明反复表明,你不能泄漏静态上下文,就像我在构造函数显示的一样,但它永远不会超出这一点.这是真的唯一不能做的事吗?

解决方法

在Java / Android中,静态变量或常量不会被垃圾回收.一旦持有它的类通过类加载器加载,它就停留在那里.类加载器对于您的应用程序中的所有类始终是相同的,并且它具有对所有类的静态引用的类(例如MyInnerClass.class).由于类加载器不会消失,因为它们被引用&因此不能收集垃圾.

就像你的例子

public class SomeClass extends SurfaceView {
  private static Context myContext;

  public MyInnerClass(Context context){
     myContext = context;        // This is bad.
  }
}

这确实很糟糕即使不存在对SomeClass的引用(例如,显示您的自定义SurfaceView的Activity已经结束),对Context的静态引用(以及SomeClass中的任何其他静态变量/常量)仍然存在,您可以认为它们都是泄漏的,因为它是不可能的垃圾收集上下文等.如果你有一个常规变量引用的东西,那么一旦包含该变量的实例没有更多的引用,整个实例包括对其他事情的引用可以而且将被垃圾回收Java甚至可以处理循环参考罚款.

对于常量,您希望发生这种情况,它通常不会坏,因为它们占用的常量和内存量不大.此外,常量不(不应该)引用占用大量内存的其他实例,如Context或Bitmap.

除了通过静态变量创建内存泄漏的可能性之外,如果您不希望在同一时间只对所有实例都只有一件事情,那么也可能会产生问题.例如,如果将SurfaceView的Bitmap保存在静态变量中,则不能有两个不同的图像.即使两个SurfaceViews不同时显示,您也可能遇到问题,因为每个新的实例都可能会覆盖旧图像,如果返回到另一个SurfaceView,则会意外显示错误的图像.我几乎肯定你不想在这里使用静态.

事实上,你的内部类是一个静态类并不意味着你必须使用静态变量 – 它只是意味着它的行为更像一个静态方法,因为它不能使用实例变量(不是静态的)你的班.

为了避免内存泄漏,您根本不应该使用静态变量.除非你做特殊的事情(例如计数一个类的实例),否则不需要使用它们.常数很好

猜你在找的Android相关文章