1

I have created a RecyclerView with a very similar design to the one mentioned

here

and even used the excellent self-supplied solution in my implementation. Basically I have a RecyclerView that expands upon click to show an extra layout component for that entry.

That worked fine however once the view was expanded it sometimes got recycled and when scrolling to new views they would sometimes appear on screen in an expanded state which isn't what I was after. To resolve this I followed the advice from

this post

and set

holder.setIsRecyclable(false);

when clicked. This also seemed to work fine.

My only issue is that I now get the following error in my logs when the app is running and multiple views are getting clicked/scrolled/expanded/recycled.

isRecyclable decremented below 0: unmatched pair of setIsRecyable() calls

As far as I can tell I have a matching call to set the view back to recyclable, so can anyone shed some more info on what is causing the above error and what I need to do to resolve it? Full snippet of offending code below, this is in my onClickListener.

if (!isViewExpanded) {
    holder.setIsRecyclable(false);
    llCompInfo.setVisibility(View.VISIBLE);
    llCompInfo.setEnabled(true);
    isViewExpanded = true;
    scores.get(getAdapterPosition()).setShowCompInfo(true);
} else {
    holder.setIsRecyclable(true);
    llCompInfo.setEnabled(false);
    isViewExpanded = false;
    scores.get(getAdapterPosition()).setShowCompInfo(false);
}
Community
  • 1
  • 1
BGH
  • 497
  • 1
  • 6
  • 18

1 Answers1

1

Keep "expanded" state in your items (adapter) and when onBind is called, use that information. You should not be messing w/ isRecycleable unless you are implementing some custom animations outside the ItemAnimator.

yigit
  • 37,683
  • 13
  • 72
  • 58
  • That is what I thought the obvious approach would be and what I tried first. In the code I originally posted scores.get(getAdapterPosition()).setShowCompInfo(true); is changing the value in the adapter that determines whether to show the view as expanded or not. But for some reason in the onBindViewHolder method it seems to ignore setVisibility.GONE based upon the adapter flag and still recycles the view as fully expanded. – BGH Jun 27 '15 at 23:25
  • Can u post that version? Also, the view is recycled as is, you should be fixing it when on bind is called. If you can share that version, fix should be trivial – yigit Jun 27 '15 at 23:40
  • 1
    When I say "originally posted" I simply mean the code in the question above. This is the relevant part of the code in the onBindViewHolder 'if (s.getShowCompInfo()) { // Set Views to View.GONE and .setEnabled(false) holder.llCompInfo.setVisibility(View.VISIBLE); holder.llCompInfo.setEnabled(true); holder.isViewExpanded = true; } else { holder.llCompInfo.setVisibility(View.GONE); holder.llCompInfo.setEnabled(false); holder.isViewExpanded = false; }' Even with that it still shows expanded. – BGH Jun 28 '15 at 03:11
  • That does not make sense. Is there a sample project you can attach, or at least link to full activity & adapter code ? – yigit Jun 28 '15 at 03:16
  • btw, it is much better if you just call setEnabled and then call notifyItemChanged() and in return, recyclerview will call onbind and also run animations. (just a side note) – yigit Jun 28 '15 at 03:17
  • Here is the full adapter code http://pastebin.com/z4nhVCAm This is my first attempt at a RecyclerView so there is no doubt many incorrect practices in there. – BGH Jun 28 '15 at 03:41
  • 1
    a couple of things: Don't set the VH as the tag, you can get it from recyclerView.getChildViewHolder(view). Also, in your onClick, you are already in the VH so why get it from the tag? (it is "this"). What you do in the animation listener is really bad (line 134). Request layout will kill the performance. On click, just change your model and call notifyItemChanged. Then write a custom ItemAnimator (or extend DefaultItemAnimator) and run your change animation there. And use the new animator api (Honeycomb) not the old one (Animation). Check DefaultItemAnimator source for details. – yigit Jun 28 '15 at 04:33