内存泄漏详细解析 - 1835434698/1835434698.github.io GitHub Wiki

内存泄漏终结

1、内存泄漏原因

内存泄漏(Memory Leak)是指程序中已动态分配的堆内存由于某种原因程序未释放或无法释放,造成系统内存的浪费,导致程序运行速度减慢甚至系统崩溃等严重后果。

Android中内存泄漏大部分情况是因为内部类导致的,内部类会持有外部类的引用,但是外部类销毁回收的时候内部类还在执行,导致外部类不能被回收。

2、防止匿名内部类内存泄漏写法

    private static final String TAG = "ThreadMainActivity";
    private int i = 0;
    private int j = 0;

    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Log.d(TAG, "onCreate");
        runTask();
    }

private void runTask() {
        Observable.create(new ObservableOnSubscribe<Object>() {
            @Override
            public void subscribe(ObservableEmitter<Object> emitter){
                try {
                    Log.d(TAG, "work run name : "+Thread.currentThread().getName());
                    workTask();
                    emitter.onNext("");
                }catch (Exception e){
                    Log.d("ThreadMainActivity", "e12 = "+e.getMessage());
                }
            }
        }).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread())
                .as(AutoDispose.autoDisposable(AndroidLifecycleScopeProvider.from(this)))
                .subscribe(new Consumer<Object>() {
                    @Override
                    public void accept(Object integer) throws Exception {
                        Log.d(TAG, "UI run i = " + i + " j = " + j + " name : " + Thread.currentThread().getName());
                        uiTask();
                    }
                });
    }

    private void uiTask() {
        j++;
        runTask();
    }

    private void workTask() throws InterruptedException {
        i = 0;
        Log.d(TAG, "work run i = "+i+" j = "+j);
        if (j >= 10){
            throw new InterruptedException();
        }
        while (i< 10){
            Log.d(TAG, "i++");
            i++;
            Thread.sleep(100);
        }
    }

此种写法有两个匿名内部类分别是ObservableOnSubscribe与Consumer,但是触发GC的时候会先把匿名内部类回收掉。

2、防止内部类内存泄漏写法

    private static final String TAG = "ThreadMainActivity";
    private int i = 0;
    private int j = 0;
    private ObservableOnSubscribe<Object> objectObservableOnSubscribe;

    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Log.d(TAG, "onCreate");
        runTask();
    }

    private void runTask() {
        objectObservableOnSubscribe = new ObservableOnSubscribe<Object>() {
            @Override
            public void subscribe(ObservableEmitter<Object> emitter){
                try {
                    Log.d(TAG, "work run name : "+Thread.currentThread().getName());
                    workTask();
                    emitter.onNext("");
                }catch (Exception e){
                    Log.d("ThreadMainActivity", "e12 = "+e.getMessage());
                }
            }
        };
        Consumer<Object> consumer = new Consumer<Object>() {
            @Override
            public void accept(Object integer) throws Exception {
                Log.d(TAG, "UI run i = " + i + " j = " + j + " name : " + Thread.currentThread().getName());
                uiTask();
            }
        };
        Observable.create(objectObservableOnSubscribe).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread())
                .as(AutoDispose.autoDisposable(AndroidLifecycleScopeProvider.from(this)))
                .subscribe(consumer);
    }

    private void uiTask() {
        j++;
        runTask();
    }

    private void workTask() throws InterruptedException {
        i = 0;
        Log.d(TAG, "work run i = "+i+" j = "+j);
        if (j >= 10){
            throw new InterruptedException();
        }
        while (i< 10){
            Log.d(TAG, "i++");
            i++;
            Thread.sleep(100);
        }
    }


    @Override
    protected void onDestroy() {
        super.onDestroy();
        Log.d(TAG, "onDestroy");
        objectObservableOnSubscribe = null;
    }

此种写法Consumer容易被回收,ObservableOnSubscribe的大部分会被回收,但是最好一个new的不容易被回收,但是可以在onDestroy使objectObservableOnSubscribe = null;几可以使其被回收。

⚠️ **GitHub.com Fallback** ⚠️