Assigned
Status Update
Comments
al...@android.com <al...@android.com>
gr...@gmail.com <gr...@gmail.com> #2
Same thing happens on version 21.0.3 of the mentioned libraries.
yb...@google.com <yb...@google.com> #3
any way to reproduce would be helpful. Also, do you have full span items ?
yb...@google.com <yb...@google.com> #4
any way to reproduce would be helpful. Also, do you have full span items ?
gr...@gmail.com <gr...@gmail.com> #5
Yes, I have.
The item clicked is spanned across all (3) columns. It has some visible views and one hidden view.
The items that are inserted below it are not spanned across all columns.
On click the clicked item (spanned across all columns) is changed so that the hidden child view is set to View.VISIBLE in onBind and notifyItemChanged is called for it.
After that new items are inserted below (those are not full span items) and notifyItemInserted is called for each of them.
For sake of clarity lets call the above scenario action A.
The inserted items are CardViews with one child that has a constant height.
I cannot promise I will manage to extract some sample app from my project.
It does not seem that the state of the backing list has anything to do with that since it can be thrown or not depending on the position to which the recycler view is scrolled to before proceeding with the actions described above.
I do not know if that is important but the non-full span item are populated with Picasso (but they have constant height).
before
_________________________top of the recycler view
|full____span_______item|first not expanded full span item
|full____span_______item|second not expanded full span item
| |
| |
| |
| |
| |
| |
_________________________bottom of the recycler view
after clicking first full span item
_________________________top of the recycler view
|full____span_______item|first expanded
|previously_hidden__part| full span item
|no_span|no_span|no_span|three non-full span items
|no_span|no_span|no_span|three non-full span items
|no_span|no_span|no_span|three non-full span items
|no_span|no_span|no_span|three non-full span items
|full____span_______item|second not expanded full span item
| |
| |
| |
_________________________bottom of the recycler view
after clicking both full span items.
_________________________top of the recycler view
|full____span_______item|first expanded
|previously_hidden__part| full span item
|no_span|no_span|no_span|three non-full span items
|no_span|no_span|no_span|three non-full span items
|no_span|no_span|no_span|three non-full span items
|no_span|no_span|no_span|three non-full span items
|full____span_______item|second expanded
|previously_hidden__part| full span item
|no_span|no_span|no_span|three non-full span items
|no_span|no_span|no_span|three non-full span items (some of the non-full span items are not fitting on the screen)
_________________________bottom of the recycler view
I think that the fact that the full span item is being redrawn with different height has something to do with that.
Because of that there is less space for other items and maybe that causes the trouble.
What I noticed (it is kind of weird behavior):
If after action A on the second expanded item the first row of non-full span items is not visible (it is below the bottom of the recycler view) - the exception is not thrown.
If after action A on the second expanded item the first row of non-full span items is fully visible so that the bottom of the first row is close to the bottom of the recycler view - the exception is not thrown.
If after action A on the second expanded item the first row of non-full span items is partially visible - the exception is thrown.
I understand it is nothing like a scenario that would allow reproduction, but this is what I can provide at the moment.
The item clicked is spanned across all (3) columns. It has some visible views and one hidden view.
The items that are inserted below it are not spanned across all columns.
On click the clicked item (spanned across all columns) is changed so that the hidden child view is set to View.VISIBLE in onBind and notifyItemChanged is called for it.
After that new items are inserted below (those are not full span items) and notifyItemInserted is called for each of them.
For sake of clarity lets call the above scenario action A.
The inserted items are CardViews with one child that has a constant height.
I cannot promise I will manage to extract some sample app from my project.
It does not seem that the state of the backing list has anything to do with that since it can be thrown or not depending on the position to which the recycler view is scrolled to before proceeding with the actions described above.
I do not know if that is important but the non-full span item are populated with Picasso (but they have constant height).
before
_________________________top of the recycler view
|full____span_______item|first not expanded full span item
|full____span_______item|second not expanded full span item
| |
| |
| |
| |
| |
| |
_________________________bottom of the recycler view
after clicking first full span item
_________________________top of the recycler view
|full____span_______item|first expanded
|previously_hidden__part| full span item
|no_span|no_span|no_span|three non-full span items
|no_span|no_span|no_span|three non-full span items
|no_span|no_span|no_span|three non-full span items
|no_span|no_span|no_span|three non-full span items
|full____span_______item|second not expanded full span item
| |
| |
| |
_________________________bottom of the recycler view
after clicking both full span items.
_________________________top of the recycler view
|full____span_______item|first expanded
|previously_hidden__part| full span item
|no_span|no_span|no_span|three non-full span items
|no_span|no_span|no_span|three non-full span items
|no_span|no_span|no_span|three non-full span items
|no_span|no_span|no_span|three non-full span items
|full____span_______item|second expanded
|previously_hidden__part| full span item
|no_span|no_span|no_span|three non-full span items
|no_span|no_span|no_span|three non-full span items (some of the non-full span items are not fitting on the screen)
_________________________bottom of the recycler view
I think that the fact that the full span item is being redrawn with different height has something to do with that.
Because of that there is less space for other items and maybe that causes the trouble.
What I noticed (it is kind of weird behavior):
If after action A on the second expanded item the first row of non-full span items is not visible (it is below the bottom of the recycler view) - the exception is not thrown.
If after action A on the second expanded item the first row of non-full span items is fully visible so that the bottom of the first row is close to the bottom of the recycler view - the exception is not thrown.
If after action A on the second expanded item the first row of non-full span items is partially visible - the exception is thrown.
I understand it is nothing like a scenario that would allow reproduction, but this is what I can provide at the moment.
gr...@gmail.com <gr...@gmail.com> #6
The fact that the full span item is being redrawn with different height has nothing to do with that. I have removed that part and it is still happening.
gr...@gmail.com <gr...@gmail.com> #7
[Comment deleted]
gr...@gmail.com <gr...@gmail.com> #8
It seems that you are onto it.
What I did is set the spanCount to 1 and then tested two cases (with and without setting setFullSpan(true) to the LayoutParams of the clickable item).
So the UI looked the same in both cases but the exception is only thrown when the setFullSpan is called for the clickable item from the description above.
What I did is set the spanCount to 1 and then tested two cases (with and without setting setFullSpan(true) to the LayoutParams of the clickable item).
So the UI looked the same in both cases but the exception is only thrown when the setFullSpan is called for the clickable item from the description above.
gr...@gmail.com <gr...@gmail.com> #9
I have achieved what I wanted by moving to GridLayoutManager.
So instaed of StaggeredGridLayoutManager and following code
StaggeredGridLayoutManager.LayoutParams layoutParams = (StaggeredGridLayoutManager.LayoutParams) viewHolder.itemView.getLayoutParams();
layoutParams.setFullSpan(true);
in onBindViewHolder for the item that I want to span across all columns.
I use GridLayoutManager like this.
int spanCount = 3;
GridLayoutManager gridLayoutManager = new GridLayoutManager(getActivity(), spanCount );
GridLayoutManager.SpanSizeLookup spanSizeLookup = new GridLayoutManager.SpanSizeLookup() {
@Override
public int getSpanSize(int position) {
if (recyclerAdapter.getItemViewType(position) == VIEW_TYPE_SPANNING_ACROSS_ALL_COLUMNS) {
return spanCount;
} else {
return 1;
}
}
};
gridLayoutManager.setSpanSizeLookup(spanSizeLookup);
It looks like everything works as expected - we'll see.
Of course that does not fix the problem with StaggeredGridLayoutManager.
So instaed of StaggeredGridLayoutManager and following code
StaggeredGridLayoutManager.LayoutParams layoutParams = (StaggeredGridLayoutManager.LayoutParams) viewHolder.itemView.getLayoutParams();
layoutParams.setFullSpan(true);
in onBindViewHolder for the item that I want to span across all columns.
I use GridLayoutManager like this.
int spanCount = 3;
GridLayoutManager gridLayoutManager = new GridLayoutManager(getActivity(), spanCount );
GridLayoutManager.SpanSizeLookup spanSizeLookup = new GridLayoutManager.SpanSizeLookup() {
@Override
public int getSpanSize(int position) {
if (recyclerAdapter.getItemViewType(position) == VIEW_TYPE_SPANNING_ACROSS_ALL_COLUMNS) {
return spanCount;
} else {
return 1;
}
}
};
gridLayoutManager.setSpanSizeLookup(spanSizeLookup);
It looks like everything works as expected - we'll see.
Of course that does not fix the problem with StaggeredGridLayoutManager.
[Deleted User] <[Deleted User]> #10
[Comment deleted]
ch...@gmail.com <ch...@gmail.com> #11
This also happens in 25.3.1. In the StaggeredGridLayoutManager # LazySpanLookup # invalidateAfter (int position) method, endPosition is sometimes equal to mData.length, causing Arrays.fill (mData, position, endPosition + 1, LayoutParams.INVALID_SPAN_ID ) ArrayIndexOutOfBoundsException error occurs.
/**
* returns end position for invalidation.
*/
int invalidateAfter(int position) {
if (mData == null) {
return RecyclerView.NO_POSITION;
}
if (position >= mData.length) {
return RecyclerView.NO_POSITION;
}
int endPosition = invalidateFullSpansAfter(position);
if (endPosition == RecyclerView.NO_POSITION) {
Arrays.fill(mData, position, mData.length, LayoutParams.INVALID_SPAN_ID);
return mData.length;
} else {
// just invalidate items in between
// if endPosition == mData.length, throw ArrayIndexOutOfBoundsException
Arrays.fill(mData, position, endPosition + 1, LayoutParams.INVALID_SPAN_ID);
return endPosition + 1;
}
}
/**
* returns end position for invalidation.
*/
int invalidateAfter(int position) {
if (mData == null) {
return RecyclerView.NO_POSITION;
}
if (position >= mData.length) {
return RecyclerView.NO_POSITION;
}
int endPosition = invalidateFullSpansAfter(position);
if (endPosition == RecyclerView.NO_POSITION) {
Arrays.fill(mData, position, mData.length, LayoutParams.INVALID_SPAN_ID);
return mData.length;
} else {
// just invalidate items in between
// if endPosition == mData.length, throw ArrayIndexOutOfBoundsException
Arrays.fill(mData, position, endPosition + 1, LayoutParams.INVALID_SPAN_ID);
return endPosition + 1;
}
}
mi...@meta.com <mi...@meta.com> #12
I can see this consistently crashing after an insert in cases where the index of next full span which needs to be invalidated is equal to the size of mData before mData was updated.
This can happen because mData is only resized after invalidation, but full span item indexes have already been shifted after the insert.
I've managed to isolate a repro for this, which you can find in the attached zip. I can upload the raw files if you prefer
This can happen because mData is only resized after invalidation, but full span item indexes have already been shifted after the insert.
I've managed to isolate a repro for this, which you can find in the attached zip. I can upload the raw files if you prefer
Description
Version used: 22.0.0
Noticed on Nexus 5 (Android 5.0.1 LRX22C).
RecyclerView with StaggeredGridLayoutManager.
On click on list item (which spans through all columns) the item is changed (enlarged) and some additional items are inserted below the clicked one. This sometimes results in below exception (I was unable to find why this is random).
java.lang.ArrayIndexOutOfBoundsException: start < 0 || end > len. start=8, end=12, len=11
at java.util.Arrays.checkStartAndEnd(Arrays.java:1732)
at java.util.Arrays.fill(Arrays.java:803)
at android.support.v7.widget.StaggeredGridLayoutManager$LazySpanLookup.invalidateAfter(StaggeredGridLayoutManager.java:2244)
at android.support.v7.widget.StaggeredGridLayoutManager.handleUpdate(StaggeredGridLayoutManager.java:1281)
at android.support.v7.widget.StaggeredGridLayoutManager.onItemsAdded(StaggeredGridLayoutManager.java:1257)
at android.support.v7.widget.RecyclerView$5.dispatchUpdate(RecyclerView.java:443)
at android.support.v7.widget.RecyclerView$5.onDispatchSecondPass(RecyclerView.java:459)
at android.support.v7.widget.AdapterHelper.consumePostponedUpdates(AdapterHelper.java:119)
at android.support.v7.widget.RecyclerView.dispatchLayout(RecyclerView.java:1966)
at android.support.v7.widget.RecyclerView.onLayout(RecyclerView.java:2237)
at android.view.View.layout(View.java:15596)
at android.view.ViewGroup.layout(ViewGroup.java:4966)
at android.support.v4.widget.SwipeRefreshLayout.onLayout(SwipeRefreshLayout.java:561)
at android.view.View.layout(View.java:15596)
at android.view.ViewGroup.layout(ViewGroup.java:4966)
at android.widget.RelativeLayout.onLayout(RelativeLayout.java:1076)
at android.view.View.layout(View.java:15596)
at android.view.ViewGroup.layout(ViewGroup.java:4966)
at android.widget.FrameLayout.layoutChildren(FrameLayout.java:573)
at android.widget.FrameLayout.onLayout(FrameLayout.java:508)
at android.view.View.layout(View.java:15596)
at android.view.ViewGroup.layout(ViewGroup.java:4966)
at android.widget.RelativeLayout.onLayout(RelativeLayout.java:1076)
at android.view.View.layout(View.java:15596)
at android.view.ViewGroup.layout(ViewGroup.java:4966)
at android.support.v4.widget.DrawerLayout.onLayout(DrawerLayout.java:907)
at android.view.View.layout(View.java:15596)
at android.view.ViewGroup.layout(ViewGroup.java:4966)
at android.widget.FrameLayout.layoutChildren(FrameLayout.java:573)
at android.widget.FrameLayout.onLayout(FrameLayout.java:508)
at android.view.View.layout(View.java:15596)
at android.view.ViewGroup.layout(ViewGroup.java:4966)
at android.widget.FrameLayout.layoutChildren(FrameLayout.java:573)
at android.widget.FrameLayout.onLayout(FrameLayout.java:508)
at android.view.View.layout(View.java:15596)
at android.view.ViewGroup.layout(ViewGroup.java:4966)
at android.widget.FrameLayout.layoutChildren(FrameLayout.java:573)
at android.widget.FrameLayout.onLayout(FrameLayout.java:508)
at android.view.View.layout(View.java:15596)
at android.view.ViewGroup.layout(ViewGroup.java:4966)
at android.widget.FrameLayout.layoutChildren(FrameLayout.java:573)
at android.widget.FrameLayout.onLayout(FrameLayout.java:508)
at android.view.View.layout(View.java:15596)
at android.view.ViewGroup.layout(ViewGroup.java:4966)
at android.widget.FrameLayout.layoutChildren(FrameLayout.java:573)
at android.widget.FrameLayout.onLayout(FrameLayout.java:508)
at android.view.View.layout(View.java:15596)
at android.view.ViewGroup.layout(ViewGroup.java:4966)
at android.view.ViewRootImpl.performLayout(ViewRootImpl.java:2072)
at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1829)
at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1054)
at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:5779)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:767)
at android.view.Choreographer.doCallbacks(Choreographer.java:580)
at android.view.Choreographer.doFrame(Choreographer.java:550)
at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:753)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5221)
at java.lang.reflect.Method.invoke(Native Method)