Android 内存泄漏 - 不要用static修饰控件

LeakCanary 工具集成

LeakCanary是android平台用于内存泄漏检测的开源工具,使用方法十分简单,其github地址:
LeakCanary Github

内存泄漏总结

Avoid using non-static inner classes in an activity if instances of the inner class could outlive the activity's lifecycle

总结来说,当内部类持有外部类的引用且它的生命周期更长时,会引发内存泄漏。

不要用static修饰控件

如下代码示例:

public class CameraViewActivity extends AppCompatActivity {
    //注意此处的static修饰符
    private static ImageView imageView;
     @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
}

对于ImageView的控件,如果设置为static会有什么影响?
当我们使用static修饰ImageView控件时,AS会提示:

Do not place android context classes in static fields, this is a memory leak.

原因:
首先被static修饰变量的生命周期,静态变量在类文件编译成字节码后,载入方法区时,就会初始化静态变量,并且静态变量会伴随整个进程(在android中即该应用的进程)一直存在。然而对于其所在的非static Activity,会在创建时在堆中申请内存,当该activity退出时,GC会依据GC_ROOT的规则遍历回收那些没有被任何地方引用的对象,但是由于该activity的context传入了静态成员ImageView中:

ImageView view = LayoutInflater.from(context).inflate(R.layout.test,null);

该ImageView的生命周期等同于整个应用,那么该activity的引用(conext)一直被持有,那么自然就始终无法被GC回收,造成内存泄漏,直到整个进程终止(体现为android application crash)。

关于ImageView是如何持有context,则需要针对PhoneWindow等窗口机制进行解析。

你可能感兴趣的:(Android 内存泄漏 - 不要用static修饰控件)