Rxjava, combLatest с утечкой памяти RxTextView

Я пытаюсь использовать combLatest с несколькими RxTextViews, и я думал, что правильно распоряжаюсь своими Disposables, но похоже, что у меня все еще возникает утечка памяти.

val one = RxTextView.afterTextChangeEvents(one)
            val two = RxTextView.afterTextChangeEvents(two)
            val three = RxTextView.afterTextChangeEvents(three)
            val four = RxTextView.afterTextChangeEvents(four)
            val five = RxTextView.afterTextChangeEvents(five)

            val disposable = Observables.combineLatest(one, two, three, four, five) { oneEvent, twoEvent, threeEvent, fourEvent, fiveEvent ->
                 //combining happening with these strings: oneEvent.view().text.toString  }
                    .skip(1) 
                    .debounce(1000, TimeUnit.MILLISECONDS)
                    .observeOn(AndroidSchedulers.mainThread())
                    .subscribe {
                        //network call
                    }
            compositeDisposable.add(disposable)
        }

А потом в своем onStop я его выбрасываю.

override fun onStop() {
    super.onStop()
    if (!compositeDisposable.isDisposed) {
        compositeDisposable.dispose()
    }
}

Я читал, что если некоторые представления упоминаются в методе onNext(), то существует потенциальное исключение NullPointerException, что, как я полагаю, и происходит. Вот мой NPE, который я получаю:

fatal Exception: java.lang.NullPointerException: view == null
       at com.jakewharton.rxbinding2.internal.Preconditions.checkNotNull(Preconditions.java:27)
       at com.jakewharton.rxbinding2.widget.RxTextView.afterTextChangeEvents(RxTextView.java:159)
       at MyFragment$setUpTextListeners$1.execute(MyFragment.kt:170)

Вот фрагмент, который я использую:

private lateinit var viewModel: MyViewModel
private lateinit var binding: FragmentMyThingsBinding

private val compositeDisposable = CompositeDisposable()

override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {

    binding = FragmentMyThingsBinding.inflate(inflater, container, false)
    viewModel = ViewModelProviders.of(this).get(MyViewModel::class.java)
    binding.viewModel = viewModel

    //calls to kick off business logic

    return binding.root
}


override fun onStart() {
    super.onStart()

    setUpTextListeners()
}

override fun onStop() {
    super.onStop()
    if (!compositeDisposable.isDisposed) {
        compositeDisposable.dispose()
    }
}

private fun setUpTextListeners() {

    val one = RxTextView.afterTextChangeEvents(one)
    val two = RxTextView.afterTextChangeEvents(two)
    val three = RxTextView.afterTextChangeEvents(three)
    val four = RxTextView.afterTextChangeEvents(four)
    val five = RxTextView.afterTextChangeEvents(five)

    compositeDisposable.add(Observables.combineLatest(one, two, three, four, five) { oneEvent, twoEvent, threeEvent, fourEvent, fiveEvent ->
            //combine here using oneEvent.view().text.toString  }
            .skip(1)
            .debounce(1000, TimeUnit.MILLISECONDS)
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe {
                //network call
            })

    }
}

person alisonthemonster    schedule 21.09.2018    source источник


Ответы (1)


Одно из ваших представлений, которое вы передаете RxTextView.afterTextChangeEvents, имеет значение null. Существует assert в той функции, которая проверяет входящий аргумент на null.

И эта проблема не связана с утечками памяти.

РЕДАКТИРОВАТЬ: изменение свойства синтетического представления для использования binding.editText устранило проблему. (Обсуждение в комментариях)

person ConstOrVar    schedule 21.09.2018
comment
Это правильно. Но это происходит только время от времени, и я не могу точно определить, почему. Любые идеи? - person alisonthemonster; 21.09.2018
comment
Не могли бы вы предоставить код класса MyFragment? Нужно исследовать это, чтобы помочь вам. - person ConstOrVar; 21.09.2018
comment
Добавлен фрагмент - person alisonthemonster; 21.09.2018
comment
Я также должен упомянуть, что я использую пейджер просмотра, который раскручивает newInstance этого фрагмента для каждой страницы. - person alisonthemonster; 21.09.2018
comment
Это правильный код val one = RxTextView.afterTextChangeEvents(one)? Где определяется передаваемый в функцию аргумент one? - person ConstOrVar; 21.09.2018
comment
Да, one — это идентификатор моего текстового представления. import kotlinx.android.synthetic.main.my_fragment.* - person alisonthemonster; 21.09.2018
comment
Не могли бы вы попробовать заменить one -> binding.one, two -> binding.two и т. д. Воспроизведется эта проблема или нет? - person ConstOrVar; 21.09.2018
comment
Хотел подождать минуту, прежде чем принять это, просто чтобы убедиться, что это исправлено, но похоже, что это так! Скрещенные пальцы! - person alisonthemonster; 23.09.2018