Android-浅析Android消息处理机制使用不当造成的内存泄漏

一.Handler使用不当造成的内存泄漏

内存泄漏危害极其严重,会造成OOM,使应用闪退。一般不容易发现,需要借助RefWatcher工具来进行检测。至于RefWatcher的使用方法,在这里本文就不再进行阐述,需要了解的朋友请自行在网上查询相关资料。

1.handler延时发送消息(sendEmptyMessageDelayed、sendMessageDelayed等方法)可能会造成内存泄漏

一般我们使用handler延时发送消息可能会这样用:

private android.os.Handler handler = new android.os.Handler() {
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            //...
            //处理消息
            //...
        }
    };

//发送消息
handler.sendMessageDelayed(Message.obtain(),100000);

咋看之下好像没有什么问题,但是如果我们在发送了消息后,马上把当前Activity关闭(调用finish()方法)。这样Activity应该会被系统回收,但是我们的消息已经发送到消息处理队列中,并且延时10秒处理,也就是说系统回收Activity时消息还没有处理完毕。所以当Activity要被回收时,由于handler持有Activity的引用,Activity而不能被系统回收,造成内存泄漏,如下图所示。

Android-浅析Android消息处理机制使用不当造成的内存泄漏_第1张图片

解决办法:

(1). 当Activity销毁时把发送的消息从消息队列中移除就可以解决内存泄漏问题,即在Activity的onDestroy方法中添加handler.removeCallbacksAndMessages(null)方法即可。

    @Override
    protected void onDestroy() {
        super.onDestroy();
        handler.removeCallbacksAndMessages(null);
    }

(2). 将Handler声明为静态类。

private static class RefWatcherHandler extends android.os.Handler {
        private final WeakReference mActivityReference;

        public RefWatcherHandler(Activity activity) {
            this.mActivityReference = new WeakReference(activity);
        }

        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            final Activity activity = mActivityReference.get();
            if (activity != null) {
                //...
                //处理消息
                //...
            } else {
                removeCallbacksAndMessages(null);
            }
        }
    }
    //使用
    private RefWatcherHandler refWatcherHandler = new RefWatcherHandler(this);
    //发送消息
    refWatcherHandler .sendMessageDelayed(Message.obtain(),100000);

2.handler.postDelayed可能会造成内存泄漏

使用handler.postDelayed是一般是这样用:

new Handler().postDelayed(new Runnable() {
                        @Override
                        public void run() {
                            //...
                        }
                    }, 100000);

如果在postDelayed之后立即关闭Activity也会造成内存泄漏,原因和上面的一样。

解决办法:

当Activity销毁时把post的Runnable移除,如下:

    @Override
    protected void onDestroy() {
        super.onDestroy();
        handler.removeCallbacks(runnable);
    }

二.Thread使用不当造成的内存泄漏

一般我们使用Thread来执行一些后台耗时的任务,如下:

    new Thread() {
        @Override
        public void run() {
            super.run();
            try {
                Thread.sleep(10000);            //模拟耗时任务
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            Log.i(TAG, "thread");
        }
    }.start();

如果耗时任务还没有执行完毕就把当前Activity关闭,就会造成内存泄漏。原因也大同小异。

解决方法:

在Activity销毁时,把线程停止即可。如下:

    @Override
    protected void onDestroy() {
        super.onDestroy();
        thread.interrupt();
    }

至此完毕,如有错误,敬请指教。

你可能感兴趣的:(Android)