在上一篇 Android内存泄漏的八种可能(上)中,我们讨论了八种容易发生内存泄漏的代码。其中,尤其严重的是泄漏Activity
对象,因为它占用了大量系统内存。不管内存泄漏的代码表现形式如何,其核心问题在于:
在Activity生命周期之外仍持有其引用。
幸运的是,一旦泄漏发生且被定位到了,修复方法是相当简单的。
Static Actitivities
这种泄漏
1 2 3 4 5 |
private static MainActivity activity; void setStaticActivity() { activity = this; } |
构造静态变量持有Activity
对象很容易造成内存泄漏,因为静态变量是全局存在的,所以当MainActivity
生命周期结束时,引用仍被持有。这种写法开发者是有理由来使用的,所以我们需要正确的释放引用让垃圾回收机制在它被销毁的同时将其回收。
Android提供了特殊的Set
类 https://developer.android.com/reference/java/lang/ref/package-summary.html#classes 允许开发者控制引用的“强度”。Activity
对象泄漏是由于需要被销毁时,仍然被强引用着,只要强引用存在就无法被回收。
可以用弱引用代替强引用。
https://developer.android.com/reference/java/lang/ref/WeakReference.html.
弱引用不会阻止对象的内存释放,所以即使有弱引用的存在,该对象也可以被回收。
1 2 3 4 5 |
private static WeakReference<MainActivity> activityReference; void setStaticActivity() { activityReference = new WeakReference<MainActivity>(this); } |
Static Views
静态变量持有View
private static View view;
1 2 3 |
void setStaticView() { view = findViewById(R.id.sv_button); } |
由于View
持有其宿主Activity
的引用,导致的问题与Activity
一样严重。弱引用是个有效的解决方法,然而还有另一种方法是在生命周期结束时清除引用,Activity#onDestory()
方法就很适合把引用置空。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
private static View view; @Override public void onDestroy() { super.onDestroy(); if (view != null) { unsetStaticView(); } } void unsetStaticView() { view = null; } |
Inner Class
这种泄漏
1 2 3 4 5 6 7 |
private static Object inner; void createInnerClass() { class InnerClass { } inner = new InnerClass(); } |
于上述两种情况相似,开发者必须注意少用非静态内部类,因为静态内部类持有外部类的隐式引用,容易导致意料之外的泄漏。然而内部类可以访问外部类的私有变量,只要我们注意引用的生命周期,就可以避免意外的发生。
避免静态变量
这样持有内部类的成员变量是可以的。
1 2 3 4 5 6 7 |
private Object inner; void createInnerClass() { class InnerClass { } inner = new InnerClass(); } |
Anonymous Classes
前面我们看到的都是持有全局生命周期的静态成员变量引起的,直接或间接通过链式引用Activity
导致的泄漏。这次我们用AsyncTask
1 2 3 4 5 6 7 |
tivity对象,因为它占用了大量系统内存。不管内存泄漏的代码表现形式如何,其核心问题在于:
幸运的是,一旦泄漏发生且被定位到了,修复方法是相当简单的。 Static Actitivities这种泄漏
构造静态变量持有 Android提供了特殊的
弱引用不会阻止对象的内存释放,所以即使有弱引用的存在,该对象也可以被回收。
Static Views静态变量持有View private static View view;
由于
Inner Class这种泄漏
于上述两种情况相似,开发者必须注意少用非静态内部类,因为静态内部类持有外部类的隐式引用,容易导致意料之外的泄漏。然而内部类可以访问外部类的私有变量,只要我们注意引用的生命周期,就可以避免意外的发生。
这样持有内部类的成员变量是可以的。
Anonymous Classes前面我们看到的都是持有全局生命周期的静态成员变量引起的,直接或间接通过链式引用
|