将打印到:http://www.jianshu.com/p/c5ac51d804fa.
1,原始地址。
在上次Android内存泄漏中,我们讨论了容易发生内存泄漏的八种代码类型。其中最严重的是活动对象的泄漏,因为它占用了大量的系统内存。不管内存泄漏的代码表示形式如何,核心问题是仍然在活动生命周期之外保存其引用。
幸运的是,一旦泄漏发生并被定位,修复方法非常简单。
2,静态活动
3,此泄漏
私有主活动活动;voidsetStaticActivity(){Activity=this;}
构造静态变量保持活动对象很容易导致内存泄漏,因为静态变量全局存在,因此在主Activity生命周期结束时仍保留引用。编写本文的开发人员有理由使用它,所以我们需要正确地发布引用,以便垃圾收集机制在被销毁时能够回收它。android提供了一个特殊的集合收集https://developer.android.com/reference/java/lang/ref/package-summary.html#classes.。
允许开发人员控制引用的“强度”。ActivityObject泄漏的原因是,当需要销毁它时,它仍然是强引用的,并且只要强引用存在,就无法恢复它。
4。可以用弱引用替换强引用。
https://developer.android.com/reference/java/lang/ref/WeakReference.html.
弱引用并不阻止对象的内存释放,因此即使存在弱引用,也可以回收对象。
私有WeakReference activityReference;voidsetStaticActivity(){activityReference=newWeakReference(This);}
5,静态视图
6,静态变量持有View
PrivatestaticView视图;voidStaticView(){view=findViewById(R.id.sv_按钮);}
因为View持有对其主机活动的引用,问题与Activity一样严重。Weak引用是一种有效的解决方案,但在生命周期结束时有另一种方法可以清除引用,而且Activity#onDestory()方法很适合将引用保留为空。
私有视图view;@OverridepublicvoidonDestroy(){super.onDestroy();if(view!=NULL){unsetStaticView();}voidunsetStaticView(){view=null;}
7、内部类
8、这种泄漏
PrivatestaticObject内部;voidcreateInnerClass(){classInnerClass(){classInnerClass{}innerClass()内=newInnerClass();}
类似于上述两种情况,开发人员必须小心使用较少的非静态内部类,因为非静态内部类包含对外部类的隐式引用,这很容易导致意外泄漏。但是,内部类可以访问外部类的私有变量,只要我们关注生命周期的引用,就可以避免事故的发生。
9,避免静态变量
10,因此可以保留内部类的成员变量。
私有对象内部;voidcreateInnerClass(){classInnerClass{}inner=newInnerClass();}
11,匿名类
都是由静态成员变量直接或间接地通过对活动的链引用来保持全局生命周期。这一次我们使用AsyncTask。
\\voidstartAsyncTask(){newAsyncTask(){@OverrideprotectedVoiddoInBackground(Void...params){while(True);}}.execute();}
12、Handler
voidcreateHandler(){newHandler(){@OverridepublicvoidhandleMessage(消息){Super.handleMessage(Message);}.postDelayed(newRunnable(){Overridepublicvoidrun(){while(True);}},Long.max_value>>1);}
13,线程
voidscheduleTimer(){newTimer()。调度(newTimerTask(){@Overridepublicvoidrun(){while(True);},Long.max_value>1);}
都是由匿名类引起的。匿名类是特殊的内部类-它们编写得更简洁。当需要一次特殊子类时,Java提供的语法糖分使表达式最小化。这种精彩而懒惰的写作很容易导致漏字。与内部类一样,只要内部类不跨越生命周期,内部类就完全没有问题。但是,这些类用于生成后台线程,这些线程是全局的,包含对创建者的引用(即对匿名类的引用),而后者又保存对外部类的引用。线程可以运行很长时间,因此始终保持对活动的引用使得在销毁时无法恢复。
这次我们无法通过删除静态成员变量来解决这个问题,因为线程与应用程序生命周期有关。为了避免泄漏,我们必须放弃简单和懒惰的编写,将子类声明为静态内部类。
静态内部类不保存对外部类的引用,从而破坏链引用。
14 AsyncTask
privatestaticclassNimbleTaskextendsAsyncTask{@OverrideprotectedVoiddoInBackground(Void...、所以对于Params){while(True);}voidstartAsyncTask(){newNimbleTask().execute();}
15、Handler
privatestaticclassNimbleHandlerextendsHandler{@OverridepublicvoidhandleMessage(Message消息){Super.handleMessage(Message);}}privatestaticclassNimbleRunnableimplementsRunnable{@Overridepublicvoidrun(){while(true);}}voidcreateHandler(){newNimbleHandler().postDelayed(newNimbleRunnable(),Long.MAX_Value>>1);}
16、TimerTask
privatestaticclassNimbleTimerTaskextendsTimerTask{@Overridepublic voidrun(){while(True);}}voidscheduleTimer(){newTimer().Schedule(newNimbleTimerTask(),Long.MAX_value>>1);}
但是,如果您坚持使用匿名类,只需在生命周期结束时中断线程。privateThreadthread;@OverridepublicvoidonDestroy(){Super.onDesty();if(线程!=NULL){线程。中断();}}voidspawnThread(){线程=newThread(){@OverridePublicvoidrun(){while(!isInterrup())}线程().Start();}
17,SensorManager
18,此泄漏
{SensorManager传感器管理器=(SensorManager)getSystemService(传感器_service);传感器传感器=senorManager.getDefault传感器(SensorT.YPE_all);}
不适当地使用Android系统服务很容易导致泄漏。为了使活动与服务交互,我们使用活动作为侦听器,并在传递事件和回调中形成引用链。只要活动保持已注册的侦听状态,引用就会一直保持,并且内存不会释放。
19,注销侦听器
私有SensorManager感觉管理器;PrivateSensorManager传感器;@OverridepublicvoidonDesty(){Super.onDesty();if(传感器!=NULL){unRegierListener();}voidunRegierListener(){senorManager.unRegierListener(此,传感器);}
>20,总结
活动泄漏的情况,其他一切都是一样的,建议将来遇到类似情况时使用相应的解决方案。只要内存泄漏一次,通过详细的检查,很容易解决,防止故障发生。21,是时候成为最佳实践了!
。