Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Let ItemAdapter supply item IDs #49

Open
DSteve595 opened this issue May 1, 2017 · 4 comments
Open

Let ItemAdapter supply item IDs #49

DSteve595 opened this issue May 1, 2017 · 4 comments

Comments

@DSteve595
Copy link

DSteve595 commented May 1, 2017

For some applications, having stable item IDs is necessary. Currently if a PowerAdapter with stable IDs is composed with a ViewFactory or varargs layoutResources, it'll lose its stable item IDs as ItemAdapter doesn't support it. I think a way to supply item IDs when using the append() methods would be helpful. Maybe for layoutResources, have them default to the layout res (which is an int)?

@BenTilbrook
Copy link
Collaborator

BenTilbrook commented May 1, 2017

This is part of a wider problem, which is ensuring composed adapters with stable item IDs form a composite adapter whose ID ranges don't accidentally overlap. If they overlapped it'd result in strange behavior in RecyclerView, which would be difficult to debug. I also don't want users to have to worry about stable IDs outside of overriding getItemId(). Adding your suggestion would compromise that and force the user to be aware of the full item ID range within the composite PowerAdapter.

Consider this related problem: what if your model IDs are strings? Many systems use UUIDs.

My thoughts right now are to change PowerAdapter.getItemId() to return an Object instead. Since an Object is unique in the system, any headers/footers would automatically have a stable ID. The challenge is how to map the objects into a range of longs in a way that isn't prone to memory leaks, and has decent performance.

@BenTilbrook
Copy link
Collaborator

Added #50 to track this potential solution.

@DSteve595
Copy link
Author

DSteve595 commented May 1, 2017

Object item IDs would be a wonderful solution, as then they'd have basically infinite levels of scope. But yeah, no idea how they could be mapped to longs effectively.

Another idea: What if, as part of the hasStableIds() contract, PowerAdapters could specify a range of IDs needed? For example:

@Override
protected long getItemIdUpperBound() {
    // Maybe my list will always be reasonably small, so:
    return 100000;
    // Or maybe it's a list of up to 5 items:
    return 4;
    // Or maybe I have no idea, and my IDs are hard to predict:
    return Long.MAX_VALUE;
}

That adapter's long getItemId() must then only return values between 0 and getItemIdUpperBound(). Maybe throw an IllegalStateException if it returns something outside.

Then, we could verify on every adapter composition that the sum of every adapter's count doesn't exceed LONG.MAX_VALUE. So an adapter with getMaximumItemIds() = Long.MAX_VALUE is fine, but if it's composed with another adapter and stable IDs are needed, throw an IllegalStateException or something. The effective getItemId() would be the composed PowerAdapter's getItemId() plus getItemIdUpperBound() + 1 for every PowerAdapter that comes before it.

ViewFactorys or varargs layoutResources would have getItemIdUpperBound() = viewCount - 1 and getItemId() = indexOfView.

It's not perfect, but it would enable a lot of cases where IDs are known and bounded (like incrementing database IDs or ViewFactorys). And it wouldn't be necessary to specify when stable IDs aren't needed.

@BenTilbrook
Copy link
Collaborator

BenTilbrook commented May 1, 2017

This unfortunately wouldn't cover many common cases, such as string IDs, or even integer IDs generated on a remote database, since communicating the bounds typically wouldn't be possible.

Thankfully, I think object IDs are possible using a WeakHashMap and/or WeakReferences.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants