我一直在创建视图时防止语境/活动内存泄漏的最佳实践学习了,我似乎无法找到的是什么,或者当它涉及到的类的静态字段是不允许一个肯定的答案。
比方说,我有这种形式的代码:
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一个时间应始终存在(当查看首先膨胀碰巧),然后一直保留,直到自己被终止应用程序。 如果是这样的话,是什么阻止位图和Canvas从保持开放,以及和填补了堆中的对象?
我曾经看到一遍又一遍地重复的唯一声明的是,你不能漏静态上下文就像我在构造函数中所显示的,但它永远不会超越这一点。 真的是你不能做的唯一的事情?
在Java / Android的一个static
变量或常量不会被垃圾收集。 它只是停留在那里,一旦拥有它的类是通过类加载器加载。 类加载器是据我所知总是您的应用,其具有对所有的类静态引用(到如一个内部的所有类别相同MyInnerClass.class
)。 由于类加载器不走你的类就不会做,要么因为它们被引用和因此不能当作垃圾收集。
就像你的榜样
public class SomeClass extends SurfaceView {
private static Context myContext;
public MyInnerClass(Context context){
myContext = context; // This is bad.
}
}
这确实是坏的。 即使没有参考SomeClass
存在(如Activity
即表明您的自定义SurfaceView
静态参照已结束) Context
(以及任何其他static
变量/常数SomeClass
将保持不变。你可以把它们全部泄露,因为它是不可能的垃圾收集Context
等,如果你有一个普通的变量引用的东西那么一旦包含变量没有更多的引用到它整个实例包括它与其他东西可以和将垃圾收集。Java的甚至可以处理循环引用实例引用罚款。
对于常量你想这样的事情发生,通常是不坏,因为常量的它们占据的数量和内存量并不大。 此外常量不(应该)引用会占用大量的内存一样其他实例Context
或Bitmap
。
除了创建内存泄漏可能通过静态变量,你也可能产生问题,如果你不希望有只为在同一时间的所有实例一件事。 例如,如果您保存Bitmap
你的SurfaceView
在一个static
变量,你不能有两个不同的图像。 即使两个SurfaceView
s的不同时显示的,你可能会遇到的问题,因为每一个新的实例可能会覆盖旧图像,如果你回到其他SurfaceView
你意外地显示错误的图像。 我几乎可以肯定你不希望使用static
这里。
你的内部类是一个事实static class
并不意味着你必须使用静态变量-它只是意味着它的行为更像是一个static
方法,因为它不能使用实例变量(那些不属于static
)在你的班。
为了避免内存泄漏,你根本不应该使用静态变量在所有。 有没有必要,除非你做特别的东西(一类的比如计数实例)使用它们。 常量是很好。
这篇文章谈论可变静态字段: http://javabook.compuware.com/content/memory/problem-patterns/memory-leaks.aspx 。 基本上,避免他们和使用常量来代替。