Status Update
Comments
yb...@google.com <yb...@google.com>
da...@gmail.com <da...@gmail.com> #2
yb...@google.com <yb...@google.com> #4
State can be monitored using OperationMonitor:
yb...@google.com <yb...@google.com> #5
da...@gmail.com <da...@gmail.com> #6
ap...@google.com <ap...@google.com> #7
yb...@google.com <yb...@google.com> #8
When you call notifyDataSetChanged, all items become invalid so you cannot get the position out of it (you can get layout position but NOT adapter position since adapter has changed).
The difference between layout position and adapter position is that layout position is the position when it was last laid out vs adapter position is guaranteed to match adapter contents. For notifyDataSetChanged, because all of the adapter contents have changed, we have no way of calculating the adapter position anymore.
Does that make sense?
da...@gmail.com <da...@gmail.com> #9
Yes, it make sense. But basically that means, I don't have a chance to know the local view type in onViewDetachedFromWindow method, because the position itself is already invalid at the moment, and holder.itemViewType contains global view type in case of Concat adapter. Can ViewHolder store its local view type the same way it handles global view type? So we don't need to calculate either position or view type every time we need correct view type?
yb...@google.com <yb...@google.com> #10
hmm, i see. We would need a new API for that but it might feel very weird (ViewHolder.getBindingAdapterViewType()) :/
Does NO_ISOLATION not work for your use case?
da...@gmail.com <da...@gmail.com> #11
I could use NO_ISOLATION or find another way to handle view types, maybe. I just wanted to do as less changes to the paging and recycler view classes and APIs as possible. Thank you for original fix, though. It would help a bit.
Also about ViewHolder.getBindingAdapterViewType(), yeah it sounds a bit off, but maybe Concat adapter should have the method like getBindingAdapterViewType(globalViewType). I haven't dig much into Concat adapter API, but I saw that you have some kind of map between local and global types and I suppose ViewTypeLookup could convert types for both strategies (Isolation and Shared) (ViewTypeStorage in API). Also ViewTypeStorage have the method like
NestedAdapterWrapper getWrapperForGlobalType(int globalViewType)
So seems like you can have adapter wrapper without using a position, like in getItemViewType(int position) in the original RV API. Maybe you can add open method to get local view type by using global.
The ConcatAdapterController already uses similar feature when it creates view holder (or triggers VH creation)
public ViewHolder onCreateViewHolder(ViewGroup parent, int globalViewType) {
NestedAdapterWrapper wrapper = mViewTypeStorage.getWrapperForGlobalType(globalViewType);
return wrapper.onCreateViewHolder(parent, globalViewType);
}
I may read the code wrong, but at a glimpse there is could be possibility to get local view type without using position, just global view type which I can get from VH.
yb...@google.com <yb...@google.com> #12
yea that could be as well. I've been trying to set up concat adapter to be as seemless as possible to the nested adapter but it does hit these cases where an explicit API becomes necessary :/.
If we were to provide this API in concat adapter, then the container adapter still needs to know that it is part of a concat adapter (and a reference to it) so I'm not sure how useful it will be (compared to also keeping a map or field in the VH yourself). Which is why i like the NO_ISOLATION solution better (and if you use layout ids as item types, that is usually good enough unless you have different VHs with the same layout)
But i guess you cannot use no isolation w/ the paging adapter :/ (though paging adapter is actually a very simple wrapper:
Description
Component used: ConcatAdapter
Version used: 1.2.0
Devices/Android versions reproduced on: any
The case is about two methods onViewRecycled and onFailedToRecycleView in ConcatAdapter. If you see the documentation of the base recycler view adapter it said that I can get a view holder position before it will be recycled by using ViewHolder#getBindingAdapterPosition() inside those two methods. But now comes ConcatAdapter who intercept those calls and execute its own code before it re-route them to nested adapters. The concat adapter executes the line which is removes viewHolder from mBinderLookup.
Concat Adapter triggers ConcatAdapterController.onViewRecycled:
The problem then comes out in nested adapter when I'm trying to get a view type of the view holder which is about to recycle:
I use holder.getBindingAdapterPosition() and receive NO_POSITION, of course. Because the Concat Adapter throws my call through ConcatAdapterController again by triggering getLocalAdapterPosition:
This method using mBinderLookup to search for the NestedAdapterWrapper for this view holder (mBinderLookup.get(viewHolder)), but the thing is that it is already gone, it was removed a moment ago in ConcatAdapterController.onViewRecycled. So now I do not see a possibility to get local view type using just a view holder in my nested adapter onViewRecycled method. And I can't use global view type from the view holder itself, because I'm using isolateViewTypes = true.
Even though the current implementation does not match the documentation of recycler view, I don't see how to use multiple view types for the nested adapter in isolation mode.