使用回调接口解决匿名实现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时,它会被立刻回收,所以即使最终我们还是使用了匿名内部类,但是却不会再发生内存泄漏了。