文章参考:http://blog.nimbledroid.com/2016/05/23/memory-leaks.htmlhtml
http://wetest.qq.com/lab/view/99.htmljava
实例代码一:
MainActivity:android
public class MainActivity extends AppCompatActivity {
TextView tv_test;
private Handler handler = new MyHandler();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tv_test = (TextView) findViewById(R.id.tv_test);
Message message = Message.obtain();
message.what = 0;
message.obj = "000";
handler.sendMessageDelayed(message,60000);
new Util(this,handler);
}
@Override
protected void onDestroy() {
super.onDestroy();
//handler.removeCallbacksAndMessages(null);
}
class MyHandler(){
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
tv_test.setText((CharSequence) msg.obj);
}
}
}
Util代码:web
public class Util {
private static Context context;
private static Handler handler;
Util(Context context,Handler handler){
this.context = context;
this.handler = handler;
}
}
因为Util中的context是static的,即其生命周期是和应用同样长的,在MainActivity方法中建立Util对象的时候,持有了MainActivity的引用(即this),致使该MainActivity没法被垃圾回收器回收,这样就形成了内存泄漏。 ide
内部类会隐式地持有了外部类。在该例子中,MyHandler会持有MainActivity的引用,而Util中的静态变量又持有了MyHandler的引用,这样仍是静态变量间接地持有了Activity,致使Activity没法被垃圾回收器回收。
另外还有其它几种常见的实例
实例一:TimerTask svg
private void scheduleTimer() {
new Timer().schedule(new TimerTask() {
@Override
public void run() {
while(true);
}
}, Long.MAX_VALUE >> 1);
}
实例二:
void spawnThread() {
new Thread() {
@Override public void run() {
while(true);
}
}.start();
}
该方法若在Activity中,因为TimerTask使用的是匿名内部类,会持有Activity的引用,所以会形成内存泄漏。其实这个是匿名内部类致使内存泄漏的一个实例。post
由于Handler是基于消息的。每次new出Handler,都会建立一个消息队列用于处理你使用handler发送的消息,形如:handler.send***Message。因为消息的发送老是会有先来后到的区别(若是只是这样都还好,毕竟再慢也不会过久,总归能够跑完,可能会延迟个几秒),可是若是你使用的是sendMessageDelayed(Message msg, long delayMillis)或postDelayed(Runnable r, long delayMillis)等发送延迟消息的时候,那基本内存泄漏发生的几率已经在90%以上了。由于handler会持有MainActivity的引用,会致使MainActivity没法销毁。
动画
private static View view;
void setStaticView() {
view = findViewById(R.id.sv_button);
}
因为View持有其宿主Activity的引用,故和缘由一实际上是同样的。this
ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(tv_test,"rotation",0,360).setDuration(2000);
objectAnimator.setRepeatCount(ValueAnimator.INFINITE);
objectAnimator.start();
若在OnDestory()中没有中止动画,则动画即时不可见,仍会一直执行下去,tv_test持有Activity的引用,故会致使Activity没法被回收spa
若有问题,欢迎加群交流:579853893