3

I have a problem with refreshing nested recyclerview with DiffResult. I have a parents list and each parent has children list. When I want to refresh whole list then I calculate DiffResult of parents list and DiffResult of children for each parent.

class Child {
  String id;
  String name;
  boolean highlighted;
}

class Parent {
  String id;
  String name;
  List<Child> children;
  DiffUtil.DiffResult result;
}

Of course I dispatch results to each adapter, bind items etc. But there is a problem with rendering proper state for each child view.

For example: Step 1 (none highlighted):

{
  parents: {
    "0": {
      "name": "parent1",
      "children": {
        "0": {
           "name": "child1",
           "highlighted": false,
        },
        "1": {
           "name": "child1",
           "highlighted": false,
        }
      }
    }
  }
}

Result on the screen:

<RecyclerView>
  <ParentView>
    <RecyclerView>
      <ChildView/> //not highlighted
      <ChildView/> //not highlighted
    </RecyclerView/>
  </ParentView/>
</RecyclerView>

It's ok.

Step 2 (only first child highlighted):

{
  parents: {
    "0": {  //areItemsTheSame: true, areContentsTheSame: false
      "name": "parent1",
      "children": {
        "0": { //areItemsTheSame: true, areContentsTheSame: false
           "name": "child1",
           "highlighted": true, //changed
        },
        "1": { //areItemsTheSame: true, areContentsTheSame: true
           "name": "child1",
           "highlighted": false,
        }
      }
    }
  }
}

Result on the screen (only first child view highlighted):

<RecyclerView>
  <ParentView>
    <RecyclerView>
      <ChildView/> //highlighted
      <ChildView/> //not highlighted
    </RecyclerView/>
  </ParentView/>
</RecyclerView>

It's ok. But step 3 (both highlighted):

{
  parents: {
    "0": {  //areItemsTheSame: true, areContentsTheSame: false
      "name": "parent1",
      "children": {
        "0": { //areItemsTheSame: true, areContentsTheSame: true
           "name": "child1",
           "highlighted": true,
        },
        "1": { //areItemsTheSame: true, areContentsTheSame: false
           "name": "child1",
           "highlighted": true, //changed
        }
      }
    }
  }
}

Result on the screen (BUG: Only second child highlighted!):

<RecyclerView>
  <ParentView>
    <RecyclerView>
      <ChildView/> //not highlighted
      <ChildView/> //highlighted
    </RecyclerView/>
  </ParentView/>
</RecyclerView>

RecyclerView "reset" all views and render only "highlighted" view only for second child.

But: I can avoid this behavior and get it works properly when I set parentRecyclerView.setItemAnimator(null) and childRecyclerView.setItemAnimator(null).

What is wrong?

piotrpawlowski
  • 767
  • 2
  • 9
  • 19

0 Answers0