I'm trying to use combineLatest with several RxTextViews and I thought that I was disposing my Disposables properly but it looks like I'm still getting a memory leak.
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)
}
And then in my onStop I dispose of it.
override fun onStop() {
super.onStop()
if (!compositeDisposable.isDisposed) {
compositeDisposable.dispose()
}
}
I read that if some Views are referenced in the onNext() method, then there’s a potential NullPointerException which is what I believe is happening. Here's my NPE I'm getting:
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)
Here's the fragment I'm using:
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
})
}
}
One of your views, that you pass to
RxTextView.afterTextChangeEvents, is null. There is assert in that function, that checks incoming argument onnull.And that problem is not connected with memory leaks.
EDIT: Changing the synthetic view property to use
binding.editTextfixed the issue. (Discussion in comments)