前言
内存泄漏指的是程序运行时未能正确回收部分内存,导致这些内存既不能被自身使用,又不能被其他程序使用,从而变成垃圾内存。一旦内存泄漏无法得到控制,该程序占用的内存就会越来越大,最终只能强行结束,否则会导致系统死机。
内存泄漏的检测
要对内存泄漏问题进行优化,首先得检测APP是否发生内存泄漏。正常情况下,一个APP占用的内存有一个峰值,达到这个峰值后,只要退出APP界面,占用的内存大小就会降下来。但是如果发生了内存泄漏,这个APP占用的内存大小是没有峰值的,随着页面的重复打开或时间的不断流逝,该APP消耗的内存越变越大,这便表示出现了内存泄漏的状况。因此,只要能监控APP的运行内存变化情况,即可间接判断这个APP是否发生泄漏。下面来看通过studio查看泄漏的步骤:
-
先通过操作产生泄漏,这时内存已经发生了泄漏
-
点击Profiler如图:
-
下面我们手动触发GC来回收无用的内存,如图:
-
反复的打开和关闭界面,如果发现App占用的内存只增不减,那么就是发生了内存泄漏。
内存泄漏的发生
之前讲述了如何检测发生了内存泄漏,为进一步观察内存泄漏现象,下面举个例子:
未能移除定时的Runnable任务
通常有需要延时处理时,常常调用Handler对象的postDelayed方法,由该方法延迟一段时间后执行设定好的Runnable任务。若要实现动画效果,则循环执行若干次postDelayed方法。这里蕴含着不晓得内存泄露风险,如不谨慎,App可能多跑几次就挂了。
比如下面的代码每隔两秒打一行日志,并在onDestroy页面退出时根据开关来判断是否移除任务,
代码如下:
public class RemoveTaskActivity extends AppCompatActivity implements OnClickListener{
private CheckBox ck_remove;
private TextView tv_remove;
private Button btn_remove;
private String mDesc="";
private boolean isRunning=false; //定时任务是否在运行
private Handler mHandler=new Handler(); //声明一个处理器对象
protected void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_remove_task);
ck_remove=findViewById(R.id.ck_remove);
tv_remove=findViewById(R.id.tv_remove);
btn_remove=findViewById(R.id.btn_remove);
btn_remove.setOnClickListener(this);
TextView tv_start=findViewById(R.id.tv_start);
tv_start.