h6ah4i / android-advancedrecyclerview

RecyclerView extension library which provides advanced features. (ex. Google's Inbox app like swiping, Play Music app like drag and drop sorting)
https://advancedrecyclerview.h6ah4i.com/
Apache License 2.0
5.32k stars 862 forks source link

java.lang.IllegalStateException: Added View has RecyclerView as parent but view is not a real child. Unfiltered index:0 #164

Closed wliu6v closed 8 years ago

wliu6v commented 8 years ago

Hi, I use expandable and draggable adapter in my app. Some users crashed when use my app, but I can't response this crash.

Here's the crash log, I want to know if there's any other people has this crash? And how to solve it?

java.lang.IllegalStateException: Added View has RecyclerView as parent but view is not a real child. Unfiltered index:0
    at android.support.v7.widget.RecyclerView$LayoutManager.addViewInt(RecyclerView.java:6071)
    at android.support.v7.widget.RecyclerView$LayoutManager.addView(RecyclerView.java:6037)
    at android.support.v7.widget.RecyclerView$LayoutManager.addView(RecyclerView.java:6025)
    at android.support.v7.widget.LinearLayoutManager.layoutChunk(LinearLayoutManager.java:1378)
    at android.support.v7.widget.LinearLayoutManager.fill(LinearLayoutManager.java:1327)
    at android.support.v7.widget.LinearLayoutManager.onLayoutChildren(LinearLayoutManager.java:556)
    at android.support.v7.widget.RecyclerView.dispatchLayout(RecyclerView.java:2713)
    at android.support.v7.widget.RecyclerView.onLayout(RecyclerView.java:3011)
    at android.view.View.layout(View.java:14858)
    at android.view.ViewGroup.layout(ViewGroup.java:4646)
    at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1673)
    at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1527)
    at android.widget.LinearLayout.onLayout(LinearLayout.java:1436)
    at android.view.View.layout(View.java:14858)
    at android.view.ViewGroup.layout(ViewGroup.java:4646)
    at android.widget.FrameLayout.layoutChildren(FrameLayout.java:453)
    at android.widget.FrameLayout.onLayout(FrameLayout.java:388)
    at android.view.View.layout(View.java:14858)
    at android.view.ViewGroup.layout(ViewGroup.java:4646)
    at android.widget.FrameLayout.layoutChildren(FrameLayout.java:453)
    at android.widget.FrameLayout.onLayout(FrameLayout.java:388)
    at android.view.View.layout(View.java:14858)
    at android.view.ViewGroup.layout(ViewGroup.java:4646)
    at android.widget.FrameLayout.layoutChildren(FrameLayout.java:453)
    at android.widget.FrameLayout.onLayout(FrameLayout.java:388)
    at android.view.View.layout(View.java:14858)
    at android.view.ViewGroup.layout(ViewGroup.java:4646)
    at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1673)
    at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1527)
    at android.widget.LinearLayout.onLayout(LinearLayout.java:1436)
    at android.view.View.layout(View.java:14858)
    at android.view.ViewGroup.layout(ViewGroup.java:4646)
    at android.widget.FrameLayout.layoutChildren(FrameLayout.java:453)
    at android.widget.FrameLayout.onLayout(FrameLayout.java:388)
    at android.view.View.layout(View.java:14858)
    at android.view.ViewGroup.layout(ViewGroup.java:4646)
    at android.view.ViewRootImpl.performLayout(ViewRootImpl.java:2035)
    at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1792)
    at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1047)
    at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:5896)
    at android.view.Choreographer$CallbackRecord.run(Choreographer.java:761)
    at android.view.Choreographer.doCallbacks(Choreographer.java:574)
    at android.view.Choreographer.doFrame(Choreographer.java:544)
    at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:747)
    at android.os.Handler.handleCallback(Handler.java:733)
    at android.os.Handler.dispatchMessage(Handler.java:95)
    at android.os.Looper.loop(Looper.java:136)
    at android.app.ActivityThread.main(ActivityThread.java:5103)
    at java.lang.reflect.Method.invokeNative(Native Method)
    at java.lang.reflect.Method.invoke(Method.java:515)
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:790)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:606)
    at de.robv.android.xposed.XposedBridge.main(XposedBridge.java:132)
    at dalvik.system.NativeStart.main(Native Method)
GauthierChan commented 8 years ago

I had the same error when using the Swipe adapter and removing/adding elements. It was related to duplicate IDs given to items. (2 items had the same ID, if I clicked on the second item -> crash).

Once I made sure every IDs were unique everything worked fine.

Hope it helps you.

wliu6v commented 8 years ago

@GauthierRoomDotMe Thanks for your reply.

I think I had already fixed this problem. It caused by something in onCreateGroupViewHolder . I had some wrong code when creating view.

Seems it not related to item id. The item id in my code is like below:

    @Override
    public long getGroupId(int groupPos) {
        return  groupPos;
    }

    @Override
    public long getChildId(int groupPos, int childPos) {
        return childPos;
    }

What's your meaning of duplicate IDs ? I think use the position as the id is OK.

crazymajax commented 8 years ago

I had the same error and the solution for me was to no longer specify my own ids. So I removed the following lines of code and it started working again:

  public MyAdapter(Context context) {
      this.context = context;
-     setHasStableIds(true)   // <----- removed this
  }

and all of this:

 -    @Override     
 -    public long getItemId(int position) {     
 -        return position;      
 -    }
h6ah4i commented 8 years ago

@crazymajax Hi. This library need stable IDs. Without stable and unique ID values, unintended item animations and crashes will be caused.

  @Override
    public long getItemId(int position) {
        // return position; <- this is not stable!

        // should returns stable value. IDs have to be kept the same value 
        // even after its position has been changed.
        return mItems.get(position).getId();
    }

related issues:

jjhesk commented 8 years ago

is that even the sdk bug from google?

kssujithcj commented 7 years ago

Hi @h6ah4i, I have same issue in my App. I have never seen this in testing but I see many crash logs from production. I have one activity, viewpager with multiple fragments and nested fragments in it. I have 1 expandable swipable draggable adapter and 4 expandable recyclerview adapters. I couldn't get line number of my code also. I am sure, i am setting unique group id for each item. I have 1 as child item id in all these recyclerview. Can you suggest me where to start debugging this?

h6ah4i commented 7 years ago

@kssujithcj Hi. Maybe this kind of error is caused by duplicate IDs or adapter state mismatch with notify* methods.

Duplicate IDs

I suspect this would be the most probable cause of the issue if you are using v0.9.x. The getGroupId() and getChildId() methods have limitation of its returning value range. If out-of-range group/child IDs are returned, duplicated flattened IDs will be generated by this library (1, 2).

Library version Group ID Child ID Note
v0.9.x 31 bit integer 32 bit integer ID value range is not checked, unsupported range bits are just ignored (masked)
v0.10.0 (*3) 28 bit integer 28 bit integer ID value range is strictly checked

(*1) Source code: How flattened ID generated in v0.9.3

(*2) Source code: How flattened ID generated in v0.10.2

(*3) How ARV uses item ID - ItemIdComposer

related issue) https://github.com/h6ah4i/android-advancedrecyclerview/issues/321

Adapter state mismatch

The RecyclerView.Adapter has notify* methods, if these methods are not used properly dataset and adapter will get into inconsistent state. Note that this library uses these methods internally and it might be what you are not intended! I think detecting this kind of error is very hard... but at least you can observe and logging these method calls by using the registerAdapterDataObserver().

kssujithcj commented 7 years ago

@h6ah4i, Thank you. This new update saved my months of quest.

11manu96 commented 7 years ago

@h6ah4i I am having the same error in my app, how do I fix it ? I understand the wrap around problem as the range of the numbers represented by the 32 bit integer is fixed. How do I go about finding the error. my app crashes when I try and open a webview in my app.

h6ah4i commented 7 years ago

@11manu96 Sorry, I do not have any more advices about this issue. If possible, can you please share your app code (or minimal example code to reproduce) with me?

11115111 commented 6 years ago

@GauthierChan your reply saved me! Thanks!