Update
Okay, so the plan is to implement 2.a only.
Here are the changes that will happen.
Constructors:
// Basic constructor to use if you don't have the adapter constructed already. Using this
// constructor requires that RecyclerView#setLayoutManager(LayoutManager lm) must
// be called before RecyclerView#setAdapter(Adapter a). Failure to do so will result in a
// runtime exception.
public LayoutManager(Context context);
// Standard constructor.
public LayoutManager(Context context, SectionAdapter adapter);
When RecyclerView#setAdapter(Adapter a);
is called, if the adapter does not implement the SectionAdapter interface, a ExpectedSectionAdapterRuntimeException
is thrown. It will print an error log message along the lines of, "Expected SectionAdapter but received Adapter instead."
If LayoutManager#onLayoutChildren(…)
is called before LayoutManager has pulled the section data from an adapter, a AdapterNotSetRuntimeException
is thrown. It will print an error log message along the lines of, "Adapter not set before layout. Instances of LayoutManager created with the LayoutManager(Context context) constructor must be added to a recycler view before the adapter is set."
New interface in LayoutManager:
interface SectionAdapter {
List<Integer> getSectionStartPositions();
}
Proposal
I've been working on the data change animation support and one thing I've decided is that having to update section first position on all the items is really annoying. I mean, the data change notification range isn't even limited to the same section.
The biggest restriction on the API is that the first section item has to be found in some way. This is because section layouts are dynamic and derived from the header state. This means there is no loss to keeping section configuration in the layout params, which gives us the nicety of embedding configuration in xml.
Bearing that in mind, here are my thoughts on the API changes to reduce the adapter burden:
1. Let SuperSLiM find section start positions
1.a Section start indicator
Only the first item in a section is marked. SuperSLiM has to do a linear search to look for this marker to properly load section data. This isn't so bad because it will only have to be done once per layout call, possibly less. However, linear search sucks, especially when you have to inflate a whole bunch of views to do it.
In just the first item.
or
params.setSectionStart(true);
Pros
Cons
- Performance for large sections may be compromised for fresh layouts and scrolling upwards.
- Have to manage the first item in a section.
1.b Section ids
In addition to the above, add unique section ids to each item, and let SuperSLiM look for the first item. Better than the above because a binary search can be used.
In all section items.
or
Pros
- Simpler to use than the current system.
- Better performance than 1.a.
Cons
- Must mark up all items.
- Still have to manage the first item in a section.
2. Provide section start positions
2.a Out-of-band channel
Provide section start positions in a second channel. This means you would have to implement an interface in your adapter and pass it in the LayoutManager constructor. Also, if you change the adapter on the RecyclerView, LayoutManager gets updated with it automatically so there is no need to manually update it.
interface SectionAdapter {
List<Integer> getSectionStartPositions();
}
The LayoutManager would pull the data from this just once for each adapter change. It would then keep it up to date according to your notify data change calls.
Pros
- Don't need to mark up any items.
- No performance loss.
- Can switch to this method during runtime with an adapter change.
Cons
- Still have to manually generate section first positions.
2.b Status quo
The current situation where you have to update and notify for the current item and any later if you are removing or adding items.
Now, I am thinking of implementing all three of these suggested changes. This means you would start with using 1.a or 1.b, and if you have performance problems, consider using 2.a.
If you have any ideas, or an opinion, please comment.