美文网首页
使用回调接口解决匿名Runnable内存泄漏问题

使用回调接口解决匿名Runnable内存泄漏问题

作者: EnzoRay | 来源:发表于2019-10-17 17:18 被阅读0次

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

相关文章

网友评论

      本文标题:使用回调接口解决匿名Runnable内存泄漏问题

      本文链接:https://www.haomeiwen.com/subject/ludvmctx.html