子线程和Handler引起的内存泄漏及解决

子线程

new Thread(new Runnable() {
    @Override
    public void run() {
        
    }
}).start();
两点内存泄漏

第一点 匿名内部类会隐式包含外部类的引用 如果Activity意外退出了 就不要指望Activity能够被回收

怎么解决 内部写一个静态内部类Thread 静态的不会包含外部类的引用

new MyThread().start();
}

static class MyThread extends Thread {
    @Override
    public void run() {
        //耗时操作
    }
}

可是如果想要外部类的内容呢???不是又需要外部类的引用了?如果外部类的实例进来不是又重蹈覆辙了?所以需要弱引用。弱引用在每一次垃圾收集器工作的时候,都会被回收

new MyThread(this).start();
}

static class MyThread extends Thread {

    WeakReference<MainActivity> weakReference;

    public MyThread(MainActivity mainActivity) {
        weakReference = new WeakReference<>(mainActivity);
    }

    @Override
    public void run() {
        //耗时操作
    }
}

Activity的内存泄漏基本解决了,但是线程依然无法被回收,而且DVM会永久保留这个线程。解决方法是简单设置一个标记位就可以了

 mThread = new MyThread(this);
 mThread.start();
}

MyThread mThread;

@Override
protected void onDestroy() {
    super.onDestroy();
    mThread.close();
}

static class MyThread extends Thread {

    WeakReference<MainActivity> weakReference;
    private boolean mRunning = false;

    public MyThread(MainActivity mainActivity) {
        weakReference = new WeakReference<>(mainActivity);
    }

    @Override
    public void run() {
        mRunning = true;
        while (mRunning) {
            //耗时操作
        }
    }

    public void close() {
        mRunning = false;
    }
}

圆满了


下面是Handler

子线程和Handler引起的内存泄漏及解决

这一通警告,就是,as编译器发出的警告。看看这个匿名内部类也是可以直接访问外部类成员的。解决方式,简单的多了,直接在onDestory的时候,

TextView tv;

private Handler mHandler = new Handler() {
    @Override
    public void handleMessage(Message msg) {
        tv.setText("111");
        super.handleMessage(msg);
    }
};

@Override
protected void onDestroy() {
    super.onDestroy();
    mHandler.removeCallbacksAndMessages(null);
}
直接把队列中的msg全部移除。他内存泄漏的原因是,那种延时发送的消息,message的target字段会维护这个Handler,而Handler内部会隐式维护Activity导致Activity无法释放。当然你也可以像Thread处理的一样去做。