【问题标题】:Q : RxJava : How the clear (CompositeDisposable) method work internallyQ : RxJava : clear (CompositeDisposable) 方法如何在内部工作
【发布时间】:2017-03-18 10:16:39
【问题描述】:

匿名类持有对封闭类的引用。

在以下示例中,我创建了一个小型 Activity。在 onCreate 方法中,我只是在另一个 Thread 上添加一个计时器,添加一个 CompositeDisposable 并在 onDestroy 中清除它。

显然没有 CompositeDisposable,它会造成内存泄漏。使用 CompositeDisposable 它不会造成任何内存泄漏,但它是如何工作的?

RxJava 只是中断线程并将 null 放在每个回调上?你能提供一些在 RxJava 源代码中完成这项工作的行吗,我想它在 dispose 方法附近的某个地方。

public class MainActivity extends AppCompatActivity {

private String TAG = "MainActivity";

private CompositeDisposable composite = new CompositeDisposable();

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    composite.add(Flowable
            .just(1)
            .timer(90, TimeUnit.SECONDS)
            .subscribeOn(Schedulers.io())
            .subscribeWith(new DisposableSubscriber<Long>() {

                @Override
                public void onNext(Long aLong) { sayHello(); }

                @Override
                public void onError(Throwable t) { sayHello(); }

                @Override
                public void onComplete() { sayHello(); }
            }));
}

@Override
protected void onDestroy() {
    super.onDestroy();

    composite.clear();
}

public void sayHello () { Log.w(TAG, "Hello everyone"); }

【问题讨论】:

    标签: java android multithreading rx-java2


    【解决方案1】:

    正是在dispose 方法的源代码中。您也可以在 IDE 中跳转到库中方法的源代码,在 IntelliJ 中它是 Windows 上的 Ctrl+B⌘B在 Mac 上,在 Eclipse 中是 F3

    不管怎样,这里是dispose方法的来源(我的cmets):

    @Override
    public void dispose() {
        if (disposed) { // nothing to do
            return;
        }
        OpenHashSet<Disposable> set; // this is the same type as our field that holds the Disposables
        synchronized (this) {
            if (disposed) { 
                return; // another thread did it while we got our lock, so nothing to do
            }
            disposed = true; // setting this flag is safe now, we're the only ones disposing
            set = resources; // the references are now in this local variable
            resources = null; // our field no longer has the references
        }
    
        dispose(set); // from here on out, only this method has the references to the Disposables
    }
    

    然后是我们在上面最后一行调用的dispose(OpenHashSet&lt;Disposable&gt;) 方法的完整代码(主要是我认为不言自明的错误处理):

    /**
     * Dispose the contents of the OpenHashSet by suppressing non-fatal
     * Throwables till the end.
     * @param set the OpenHashSet to dispose elements of
     */
    void dispose(OpenHashSet<Disposable> set) {
        if (set == null) {
            return;
        }
        List<Throwable> errors = null;
        Object[] array = set.keys();
        for (Object o : array) {
            if (o instanceof Disposable) {
                try {
                    ((Disposable) o).dispose();
                } catch (Throwable ex) {
                    Exceptions.throwIfFatal(ex);
                    if (errors == null) {
                        errors = new ArrayList<Throwable>();
                    }
                    errors.add(ex);
                }
            }
        }
        if (errors != null) {
            if (errors.size() == 1) {
                throw ExceptionHelper.wrapOrThrow(errors.get(0));
            }
            throw new CompositeException(errors);
        }
    }
    

    如您所见,在该方法结束时,set 现在可以被垃圾回收,因为没有人持有对它的引用。

    【讨论】:

      猜你喜欢
      • 2017-01-05
      • 1970-01-01
      • 1970-01-01
      • 2018-09-11
      • 2018-03-21
      • 1970-01-01
      • 1970-01-01
      • 2021-12-03
      • 1970-01-01
      相关资源
      最近更新 更多