In this document we will describe how to build your own
DiffSection. The Sections API already provides two implementations that cover most frequent use cases in
DataDiffSection. You should write your own
DiffSection if the given implementations do not suffice for your use case, as the complexity and chances of introducing subtle errors are both high.
A diff section spec defines a section that explicitly outputs insert, update, and remove changes on the section hierarchy.
Diff section specs explicitly manage insertions, removals, and updates that a section performs whenever its states and props change. You will find Diff Sections at the leaves of every section tree as they are the sections that actually specify the changes to be made to a list.
One example where you might want a custom diff section is if you receive the data you want to display in the form of incremental updates or diffs. This might happen if you're using a specialised diffing algorithm to process your data.
DataDiffSection utilises a familiar Android's DiffUtil.
Let's use the example of SingleComponentSection to describe how to write diff section specs. Here is a snippet of
As you can see, diff section specs use the
@DiffSectionSpec annotation. Implementing a diff section spec requires little boilerplate. You only have to write one method annotated with
The method annotated with
@OnDiff must have as its first and second argument a SectionContext and a ChangeSet respectively. Following these two arguments, your
@OnDiff method can also accept any number of arguments annotated with
These props and state have a special type:
Diff<T>. If your prop is defined in another annotated method like
@Prop String prop1, it must be defined as
@Prop Diff<String> prop1 when being used in the
@OnDiff method. The reason for this
Diff<T> type wrapper is so we can compare previous prop values with new prop values when computing changes.
ChangeSet argument of the
@OnDiff method is used by the Diff section spec to specify how the section changes in response to new data. The
@OnDiff method will always be called with the current and previous props and state values (hence the
Diff<T> type). The expectation is that you'd be able to use the current and previous values to determine how to update the items being rendered.
When you've determined what changes need to be made, you should call the corresponding method on the
ChangeSet object. These methods correspond to
notifyItem* methods. You can get a quick idea of how this works in SingleComponentSectionSpec#onDiff:
- If we don't have a new
component.getNext() == null) then we want to change the list by removing that row.
- Else if we have a new
Componentand no previous component, we want to insert a new row.
- If both an old component and a new component exists, we just want to update that row to the new component.
Note, the indexes used in the
ChangeSet method calls, they're relative to the current section. Index 0 in
SingleComponentSectionSpec might actually be index 100 in the final list depending on the section hierarchy. The framework will take care of translating local indexes to global indexes when processing the