Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using RxJava inside RecyclerView Adapter

So a few weeks ago i asked this question: recyclerview periodic ui child updates.

And today i want to refactor that funcionality using Rxjava. It's actually pretty simple, i accomplish the following way:

 @Override
    public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {

                if (friend.getGameStatus().equals(GameStatus.INGAME)) {
                    holderOnline.startRepeatingTask();
                } else {
                    holderOnline.stopRepeatingTask();
                } 
    }


class MyViewHolderOnline extends RecyclerView.ViewHolder {

    private Subscription subscribe;

        public MyViewHolderOnline(View itemView) {
            super(itemView);
            ButterKnife.bind(this, itemView);

        }

        public void startRepeatingTask() {
            subscribe = Observable.interval(updateInterval, TimeUnit.MILLISECONDS)
                    .map(aLong -> current.getGameStatusToPrint())
                    .subscribeOn(Schedulers.io())
                    .observeOn(AndroidSchedulers.mainThread())
                    .subscribe(new Subscriber<String>() {
                        @Override public void onCompleted() { }
                        @Override public void onError(Throwable e) { }

                        @Override
                        public void onNext(String gameStatusToPrint) {
                            gameStatus.setText(gameStatusToPrint);
                        }
                    });
        }

        void stopRepeatingTask() {
            if(subscribe != null && !subscribe.isUnsubscribed())
                subscribe.unsubscribe();
        }
    }

The problem however is different. I have a navigationDrawer implemented with Activities that are Paused and not Destroyed when switched. So, after i switch to the activity that don't contains this adapter, the observable keeps on sending stuff because its a periodic interval Observable. So my question is, what should i do? I need to unsubscribe when the activity is paused, but i have no idea how since to, and also how to subscribe back. Any help or ideas?

like image 613
johnny_crq Avatar asked Jul 08 '15 11:07

johnny_crq


1 Answers

So, if I understand you correctly, one way to solve your problem is to answer the question: In an Activity that contains a RecyclerView, how do I get references to all the ViewHolders that are currently displayed/bound?

For example, to stop all the updates you could then do the following in the onPause() of your Activity:

// assuming you are using a LinearLayoutManager:
final int firstVisibleIndex = mLinearLayoutManager.findFirstVisibleItemPosition();
final int lastVisibleIndex = mLinearLayoutManager.findLastVisibleItemPosition();

for (int i = firstVisibleIndex; i <= lastVisibleIndex; i++) {
    YourViewHolder viewHolder = (YourViewHolder) findViewHolderForAdapterPosition (i);
    viewHolder.stopRepeatingTask();
}

And likewise, you could restart the tasks in the onResume of your Activity.

BUT: Now that I wrote this I am not sure whether there may be ViewHolders beyond the visible area of the RecyclerView (i. e. before the first or after the last visible item) that are already bound but that would not be reached with this method. If that turns out to be the case you can still iterate over all indices of the items in your adapter and just discard any null return values.

like image 113
david.mihola Avatar answered Nov 08 '22 13:11

david.mihola