使用回调接口解决匿名实现Runnable导致的内存泄漏问题

使用回调接口解决匿名实现Runnable内存泄漏的问题 在Android开发中经常会看到这样的代码:

public class MyActivity extends Activity { ... new Thread(new Runnable() { @Override public void run() { //具体实现 } }).start(); }

开辟一个线程去执行一个耗时操作是常见的做法,但是在Android开发中,诸如Activity、Fragment这种生命周期不确定的类(周期长的情况就是一直不关闭当前Activity/Fragment,周期短的情况就是很快的关闭了当前Activity/Fragment),在生命周期短的情况下,由于匿名内部类会隐式持有外部类的引用,因此会导致外部类无法被回收,最终导致内存泄漏。
我们知道只有匿名内部类和非静态内部类会隐式持有外部类的引用,所以我们第一个想法就是使用外部类来解决这个问题,比如我们可以在外部创建一个类实现Runnable接口,再在Activity中实例化这个类:
public class MyRunnable extends Runnable {@Override public void run() { //具体实现 ] }public class MyActivity extends Activity { ... new Thread(new MyRunnable()).start(); }

这样确实解决了内存泄漏的问题,但是这种做法有一个弊端,就是在有非常多的需求时,那就必须要创建非常多的实现了Runnable的外部类来满足各个需求,并且如果我需要使用到Activity中的变量时,还需要将变量传递到这些类中,非常的麻烦,所以这种做法在大型项目中根本不可取。
【使用回调接口解决匿名实现Runnable导致的内存泄漏问题】既要能有一个外部类解决内存泄漏的问题,又要能在Activity中去写我具体的逻辑而不用将变量再传递到外部类中,仔细一想,这不正是回调接口吗?
public interface MyInterface { void doSomething(); }public class MyRunable implements Runnable {private WeakReference mInterface; public MyRunnable(MyInterface mInterface) { this.mInterface = new WeakReference<>(mInterface); }@Override public void run() { mInterface.get().doSomething(); ] }public class MyActivity extends Activity { ... new Thread(new MyRunnable(new MyInterface() { @Override public void doSomething() { //具体实现 } })).start(); }

通过回调接口,我们将具体实现放在了Activity中编写,但是我们注意到,这个接口在MyRunnable中是以弱引用的方式被持有的,所以在GC时,它会被立刻回收,所以即使最终我们还是使用了匿名内部类,但是却不会再发生内存泄漏了。

    推荐阅读