Правильный способ утилизации Rx Disposable в презентере при смене ориентации - PullRequest
0 голосов
/ 15 января 2019

Проблема: когда я пытаюсь повернуть телефон сразу после PullToRefresh, мой Observable не завершит свою работу из-за метода dispose (), который я вызывал в onPause. Я понимаю, почему это происходит, но я понятия не имею, как распорядиться без потери результата. Если я не вызываю dispose, все работает отлично, но я хочу правильно утилизировать Disposable, чтобы не было проблем с утечками памяти и т. Д.

Моя базовая ведущая:

abstract class BasePresenter<T> {

    private var view: WeakReference<T>? = null

    /**
     * View reference
     * */
    fun getView(): T? = if (view != null) view!!.get() else null

    /**
     * We should call it in onResume() method in fragment
     * */
    fun bindView(view: T?) {
        if (view != null) {
            this.view = WeakReference(view)
            updateView()
        }
    }

    /**
     * We should call it in onPause() method in fragment
     * */
    fun unbindView() {
        view = null
        dispose()
    }

    protected abstract fun updateView()

    protected abstract fun dispose()
}

Мой базовый вариант использования:

abstract class UseCase<TResult, in TParam> {

    /**
     * Creates a new instance of [Observable] for specified params
     * @param params Params to create [Observable]
     */
    abstract fun createObservable(params: TParam?): Observable<TResult>

    /**
     * [Observable] which executes UseCase logic for specified params
     * @param params Params to create [Observable]
     */
    fun observable(params: TParam?): Observable<TResult> =
        createObservable(params).doOnError { }

    /**
     * [Observable] with null params
     */
    fun observable() = observable(null)
}

В представлении:

...

override fun onResume() {
    super.onResume()
    presenter.bindView(this@MainFragment)
}

override fun onPause() {
    super.onPause()
    presenter.unbindView()
}
...

Это наблюдаемый код в презентере (обработка некоторых сетевых ответов):

fun update() {
    setRefreshing(true)

    getDataDisposable?.dispose()
    getDataDisposable = getDataUseCase
        .observable(param)
        .subscribeOn(Schedulers.io())
        .observeOn(AndroidSchedulers.mainThread())
        .switchIfEmpty {
            setRefreshing(false)
        }
        .subscribe { data ->
            [some manipulations with data]
            setRefreshing(false)
        }
}

Если я не называю это, все (конечно) работает как положено:

override fun dispose() {
    getDataDisposable?.dispose()
}

1 Ответ

0 голосов
/ 16 января 2019

Наконец-то нашли решение. Теперь я располагаю Disposable только при нажатии кнопки «назад» и не распоряжаюсь ею при просмотре без присмотра. Итак, я добавил метод к базовому докладчику:

...

/**
 * Method that should be called on back button click in fragment
 * It's planned that all [Disposable] objects will be disposed in implementation of this method
 * */
abstract fun onBackButtonClicked()

...

Ведущий:

...

override fun onBackButtonClicked() {
    getChartDataDisposable?.dispose()
}

...

Просмотр (фрагмент):

...

override fun onBackButtonClicked() {
    presenter.onBackButtonClicked()
    navigator.back()
}

...

И какая-то логика для перехвата. Нажмите кнопку аппаратного возврата:

Интерфейс:

interface OnBackButtonClickListener {
    fun onBackButtonClicked()
}

Базовый фрагмент:

abstract class BaseFragment : Fragment(), OnBackButtonClickListener {

    ...

    override fun onResume() {
        super.onResume()
        (ctx as MainActivity).currentBackPressListener = this@BaseFragment
    }

    override fun onPause() {
        super.onPause()
        (ctx as MainActivity).currentBackPressListener = null
    }

    ...
}

Наконец, переопределен метод onBackPressed () в действии:

class MainActivity : AppCompatActivity() {

    ...

    var currentBackPressListener: OnBackButtonClickListener? = null

    ...

    override fun onBackPressed() {
        currentBackPressListener?.onBackButtonClicked()
    }

    ...
}
...