1

I've got a presenter that is created for the RecyclerView.Adapter. The presenter has a method to call into the API layer, then change some local data values. This is implemented as an Rx chain:

public void doStuff(Object args) {
    mRemote.doStuff(args)
            .doOnNext(count -> mLocal.setStuffCount(count))
            .firstOrError()
            .subscribeOn(mSchedulerProvider.io())
            .observeOn(mSchedulerProvider.ui())
            .subscribe(...)
    <...>

This method might be called several times with different arguments, and therefore generate different subscriptions. As I understand, RxJava will unsubscribe onComplete or onError. However, it is possible that there are, for example, 5 subscriptions created, and before they are resolved, the user moves on from the fragment, and therefore the Adapter is no longer relevant and should be collected. However, as I understand, it won't be collected cause of the active subscriptions, until those are resolved.

Normally I link the presenter with the related view, then store all subscriptions in a CompositeDisposable and clear the disposable when the lifecycle suggests it's time to clear (for example, a view goes to the onPause state). I could implement a similar approach here, however that means I would have to:

1) Establish a relationship between a view and the adapter, so that when the view's lifecycle method is triggered, it will take the adapter and invoke an unsubscribe method on it, which will then take the presenter and invoke clear(). Could I rely on onDetachedFromRecyclerView for that? Or would I have to do that manually?

2) Each time my presenter method to do stuff is called, I'll be creating a new subscription, which means the CompositeDisposable will grow in size until who know's what. Although the call has been executed, the disposable is still referenced in the CompositeDisposable.

I have a feeling there's a simpler solution here so hoping someone might point me at it.

EDIT:

Another solution that comes to mind, would be to create a presenter for each ViewHolder and link subscription to the binding and recycling of the holder. However, that means keeping a few more presenters hanging around - but the approach seems a bit cleaner.

vkislicins
  • 3,331
  • 3
  • 32
  • 62
  • So the Observable stuff are in your presenter? Don't you have at least basic lifecycle events at the presenter? – yosriz Mar 16 '17 at 18:36
  • Yes, Rx chain and `CompositeDisposable` is in my presenter. Yes, `Presenter` is lifecycle-agnostic on purpose. I mean I can add methods to it that I'll call on lifecycle events, however which lifecycle events to use in an `Adapter`? Anyway, have a look at my own answer, might make more sense. – vkislicins Mar 16 '17 at 21:47

1 Answers1

0

Not sure if this is going to be useful to anyone but this is how I've solved this problem.

I ended up merging my Presenters while keeping different View interfaces for the ViewHolder and the Fragment (will call them ViewHolderView and FragmentView).

I liked the idea of having a Presenter for each ViewHolderView, however, it didn't really solve my problem. I was keeping my CompositeDisposable inside the Presenter, but with that approach, I had to move it out to the Adapter level and keep a reference to the Disposable inside my ViewHolder. Similar to the answer suggested here

I didn't like the idea of manipulating the Adapter from the Fragment lifecycle manually as I was already calling subscribe() and unsubscribe() on FragmentView, and onDetachedFromRecyclerView is not called unless you nullify the adapter on the RecyclerView

The solution was to merge my Adapter presenter with my Fragment presenter while keeping the ViewHolderView interface. So I ended up with a contract for one Presenter, and two separate View interfaces, and I'm passing the Presenter to the Adapter. When FragmentView unsubscribes, it cleans up everything.

Community
  • 1
  • 1
vkislicins
  • 3,331
  • 3
  • 32
  • 62