CompositeDisposable导致内存泄漏,直到清除或处置被调用?

时间:2019-02-25 06:04:07

标签: java android rx-java2

添加到Disposable的每个CompositeDisposable都会被CompositeDisposable强烈引用,直到CompositeDisposable被清除或处置。这样可以防止收集由订户(一次性)强烈引用的对象。

在添加到Disposable之前,我应该将所有WeakReference包装到CompositeDisposable吗?或者只是忽略并让CompositeDisposable将来被清除。

1 个答案:

答案 0 :(得分:0)

订阅时上游强烈引用下游。 当上游未完成任务时,最终 Disposable 观察者仍然可以被此容器处置。

import io.reactivex.disposables.Disposable
import io.reactivex.exceptions.CompositeException
import io.reactivex.internal.disposables.DisposableContainer
import java.util.*
import kotlin.collections.ArrayList

class WeakDisposableContainer : DisposableContainer, Disposable {

    private val container = WeakHashMap<Disposable, Any>()

    @Volatile
    private var disposed = false

    override fun add(d: Disposable): Boolean {
        if (!disposed) {
            synchronized(this) {
                if (!disposed) {
                    container[d] = Unit
                    return true
                }
            }
        }
        d.dispose()
        return false
    }

    override fun remove(d: Disposable): Boolean {
        if (delete(d)) {
            d.dispose()
            return true
        }
        return false
    }

    override fun delete(d: Disposable): Boolean {
        if (disposed) return false
        synchronized(this) {
            if (disposed) return false
            return container.remove(d) != null
        }
    }

    override fun isDisposed(): Boolean = disposed

    override fun dispose() {
        clear()
        disposed = true
    }

    fun clear() {
        if (disposed) return
        val d: Iterable<Disposable>
        synchronized(this) {
            if (disposed) return
            d = ArrayList(container.keys)
            container.clear()
        }
        val err = d.mapNotNull { catchThrowable { it.dispose() } }
        if (err.isNotEmpty()) throw CompositeException(err)
    }
}

inline fun catchThrowable(block: () -> Unit): Throwable? = try {
    block()
    null
} catch (e: Throwable) {
    e
}