RxJava的clear(复合一次性)方法如何在内部工作



匿名类保存对封闭类的引用。

在下面的示例中,我创建了一个小型活动。在onCreate方法中,我只是在另一个线程上添加一个计时器,添加一个复合一次性并在onDestroy中清除它。

显然,如果没有复合一次性用品,它会产生内存泄漏。使用复合材料一次性,它不会产生任何内存泄漏,但它是如何工作的?

RxJava 是否只是中断线程并在每次回调时都输入 null?你能提供一些在RxJava源代码中做到这一点的行吗?我想它在处置方法附近的某个地方。

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"); }

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

无论如何,这是dispose方法的来源(我的评论(:

@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<Disposable>)方法的完整代码(主要是错误处理,我认为这是不言自明的(:

/**
 * 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进行垃圾回收,因为没有人持有对它的引用。

最新更新