美文网首页
使用回调接口解决匿名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