2

I have a RecyclerView in Fragment, item clicks are handled using RxJava2 as explained in this SO answer, It's working fine in non fragments.

private PublishSubject<Place> itemViewClickSubject = PublishSubject.create();

@Override
    public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.search_result_view, parent, false);

        ViewHolder viewHolder = new ViewHolder(view);

        // convert click events into reactive stream
        RxView.clicks(view)
                .takeUntil(RxView.detaches(parent))
                // viewHolder.getPlace() is null until it get bound
                .map(__ -> viewHolder.getPlace())
                .subscribe(itemViewClickSubject);

        return viewHolder;
    }

When the RecyclerView in the fragment it works fine only for one time. On item click fragment is replaced with another fragment. After back press, RecyclerView fragment appears but clicks doesn't work anymore.

It works if I remove the .takeUntil(RxView.detaches(parent)) line. I think it's required to break RxView click's strong bindings with the the RecyclerView when it is not displayed (Detached). How can I solve the issue? I am looking to solve the issue using one of attach/detach events, any suggestion would be great!. Thanks.

Ruwanka De Silva
  • 3,555
  • 6
  • 35
  • 51
  • 1
    You should setup click in onBindViewHolder – Wrobel Jun 27 '17 at 11:51
  • @Wrobel Thanks for the suggestion, it works great. Still I am confused about the use of `.takeUntil(RxView.detaches(parent))` part. What would be the reason for use of that in the original SO answer. Now I think since it doesn't do any unsubscribe, having that part in the first place makes no sense. Please correct me. – Ruwanka De Silva Jun 28 '17 at 15:56
  • Because You need takeUntil() to avoid memory leaks – Wrobel Jun 29 '17 at 06:09
  • @Wrobel Ok, can you please explain how it happens. Answer would be nice if you can. Another question, so how can I do that in side `onBindViewHolder` I don't have any reference to parent there. Does parent is always points to parent recycle view? If so I can use that in side `takeUntil()`. – Ruwanka De Silva Jun 29 '17 at 15:06

1 Answers1

6

To answer your question and comments I send my entire solution for RecylerView + RxJava:

private PublishSubject<Place> itemViewClickSubject = PublishSubject.create();

@Override
public void onBindViewHolder(ViewHolder viewHolder, int position) {
    RxView.clicks(viewHolder.itemView) //viewHolder.itemView here You have access to view
            .map(aVoid -> viewHolder.getPlace())
            .subscribe(itemViewClickSubject);
}

@Override
public void onDetachedFromRecyclerView(RecyclerView recyclerView) {
    itemViewClickSubject.onComplete(); //here we avoid memory leaks
}
Wrobel
  • 1,042
  • 12
  • 21
  • 3
    Isn't the method `onComplete()`? Where do you unsubscribe the `RxView.clicks`? – Shujito Aug 03 '17 at 07:56
  • 1
    We not need to unsubscribe Rx.View click, see this answer: https://stackoverflow.com/questions/41482036/should-i-unsubscribe-when-using-rxbinding, Yes, it's onComplete(), I fixed this misspelling – Wrobel Nov 27 '18 at 09:46