在Android开发中经常要开辟一个线程去执行耗时操作,常见的代码如下:
public class MyActivity extends Activity {
...
new Thread(new Runnable() {
@Override
public void run() {
//具体实现
}
}).start();
}
由于匿名内部类会隐式持有外部类的引用,因此会导致外部类无法被回收,最终导致内存泄漏。此时我们可以在外部创建一个类实现Runnable接口来解决这个问题,但是在有非常多的需求时,那就必须要创建非常多的实现了Runnable的外部类来满足各个需求,并且如果我需要使用到Activity中的变量时,还需要将变量传递到这些类中,非常麻烦。既要能有一个外部类解决内存泄漏的问题,又要能在Activity中去写具体的逻辑而不用将变量再传递到外部类中,接口不就可以刚好解决吗?这里是一个在子线程中更新数据,然后在主线程中显示数据的业务,代码如下:
首先创建一个接口:
public interface AndroidCallbackRunnableInterface<T> {
T doRun();
void androidMainThreadCallback(T result);
}
public class AndroidCallbackRunnable implements Runnable{
Handler mHandler = new Handler();
private WeakReference<AndroidCallbackRunnableInterface> mRunnableInterface;
public AndroidCallbackRunnable(AndroidCallbackRunnableInterface runnableInterface){
mRunnableInterface = new WeakReference<>(runnableInterface);
}
@Override
public void run() {
if(mRunnableInterface != null && mRunnableInterface.get() != null){
final Object result = mRunnableInterface.get().doRun();
final AndroidCallbackRunnableInterface androidCallbackRunnableInterface = mRunnableInterface.get();
mHandler.post(new Runnable() {
@Override
public void run() {
androidCallbackRunnableInterface.androidMainThreadCallback(result);
}
});
}
}
}
public class DataCenter {
private static DataCenter mDataCenter;
private int cnt = 0;
public static DataCenter getInstance(){
if(mDataCenter == null){
synchronized(DataCenter.class){
if(mDataCenter == null){
mDataCenter = new DataCenter();
}
}
}
return mDataCenter;
}
public int incData(){
int count = ++cnt;
return count;
}
}
final TextView tvHello = findViewById(R.id.hello);
AndroidCallbackRunnable runnable = new AndroidCallbackRunnable(new AndroidCallbackRunnableInterface() {
@Override
public Object doRun() {
int cnt = 0;
for(int i = 0; i < 5; i++){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
Log.d("MainActivity","i==" + i);
cnt = DataCenter.getInstance().incData();
}
return cnt;
}
@Override
public void androidMainThreadCallback(Object result) {
tvHello.setText(result+"");
}
});
Thread mThread = new Thread(runnable);
mThread.start();
通过回调接口,我们将具体实现放在了Activity中编写,这个接口在MyRunnable中是以弱引用的方式被持有的,所以在GC时,它会被立刻回收,所以即使最终我们还是使用了匿名内部类,但是却不会再发生内存泄漏了。
网友评论