6

I have a RecyclerView where I'm getting the exception below. I've only gotten the exception on Crashlytics, I've never managed to reproduce the issue myself despite using that activity heavily every day.

The way I inflate my view on onCreateViewHolder is:

View v = LayoutInflater.from(parent.getContext())
                    .inflate(R.layout.list_item, parent, false);

There is another view type, which comes from the MoPub native ad.

Any idea what the issue could be?

Caused by java.lang.IllegalStateException: The specified child already has a parent. You must call removeView() on the childs parent first.
           at android.view.ViewGroup.addViewInner(ViewGroup.java:4438)
           at android.view.ViewGroup.addView(ViewGroup.java:4274)
           at android.view.ViewGroup.addView(ViewGroup.java:4215)
           at android.support.v7.widget.RecyclerView$5.addView(RecyclerView.java:711)
           at android.support.v7.widget.ChildHelper.addView(ChildHelper.java:107)
           at android.support.v7.widget.RecyclerView$LayoutManager.addViewInt(RecyclerView.java:7877)
           at android.support.v7.widget.RecyclerView$LayoutManager.addView(RecyclerView.java:7835)
           at android.support.v7.widget.RecyclerView$LayoutManager.addView(RecyclerView.java:7823)
           at android.support.v7.widget.LinearLayoutManager.layoutChunk(LinearLayoutManager.java:1565)
           at android.support.v7.widget.LinearLayoutManager.fill(LinearLayoutManager.java:1511)
           at android.support.v7.widget.LinearLayoutManager.scrollBy(LinearLayoutManager.java:1325)
           at android.support.v7.widget.LinearLayoutManager.scrollVerticallyBy(LinearLayoutManager.java:1061)
           at android.support.v7.widget.RecyclerView$ViewFlinger.run(RecyclerView.java:4726)
           at android.view.Choreographer$CallbackRecord.run(Choreographer.java:894)
           at android.view.Choreographer.doCallbacks(Choreographer.java:696)
           at android.view.Choreographer.doFrame(Choreographer.java:628)
           at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:880)
           at android.os.Handler.handleCallback(Handler.java:815)
           at android.os.Handler.dispatchMessage(Handler.java:104)
           at android.os.Looper.loop(Looper.java:207)
           at android.app.ActivityThread.main(ActivityThread.java:5728)
           at java.lang.reflect.Method.invoke(Method.java)
           at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:793)
           at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:683)

Edit: code

@Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        if (viewType == MoPubStreamAdPlacer.CONTENT_VIEW_TYPE) {
            View v = LayoutInflater.from(parent.getContext())
                    .inflate(R.layout.list_item, parent, false);
            ViewHolder vh = new ViewHolder(this, v);
            return vh;
        } else {
            final MoPubAdRenderer adRenderer = streamAdPlacer.getAdRendererForViewType(viewType);
            if (adRenderer == null) {
                MoPubLog.w("No view binder was registered for ads in MoPubRecyclerAdapter.");
                // This will cause a null pointer exception.
                return null;
            }
            return new MoPubRecyclerViewHolder(
                    adRenderer.createAdView((Activity) parent.getContext(), parent));
        }


    }
casolorz
  • 8,486
  • 19
  • 93
  • 200
  • Can you share your adapter code? Specifically the code for onCreateViewHolder() & onBindViewHolder(). – Doron Yakovlev Golani Aug 15 '17 at 19:40
  • Added the `onCreateViewHolder`, the `onBindViewHolder` is pretty large, don't think it will fit, mostly just logic around setting text fields and so on, is there some particular thing there that I should be copying? – casolorz Aug 15 '17 at 19:45
  • I wonder how you are creating the views. According to the message, you might be returning a view already used somewhere else. – Doron Yakovlev Golani Aug 15 '17 at 19:50
  • Isn't this where the view is created? `View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_item, parent, false);`? The `onBindViewHolder` code doesn't create any views, just sets text fields, colors, etc. When the `ViewHolder` is created all I do is call `findViewById` for each view inside of it. – casolorz Aug 15 '17 at 19:53
  • You are correct. The problem is that it is crashing... so something is probably not as it should be ;) Are you doing anything unusual (perhaps you can try to comment out most of the adapter code and see if it still misbehaves. – Doron Yakovlev Golani Aug 15 '17 at 19:59
  • The problem is that I can't reproduce it. Only happens to some of my users and I only see it on Crashlytics, I've never actually had a user report it. Of hundreds of thousands of users this last month, most of whom would have gone into this screen, only 40 crashed. I'm actually wondering if one of the mediated native ad adapters could be doing it wrong since they seem to inflate the ad view themselves. – casolorz Aug 15 '17 at 20:02
  • That would make a lot of sense. Perhaps you can try to remove the parent, if one exists, before you return the ad View. – Doron Yakovlev Golani Aug 15 '17 at 20:31
  • Yeah I guess I can do that on my next version and see how it turns out, thanks for the suggestion. – casolorz Aug 15 '17 at 20:36
  • Hi @casolorz I have same problem. Please update if you fixed. – Hoang Duc Tuan Nov 20 '17 at 08:26
  • @HoangDucTuan I still have the issue but a lot less than I used to. The `false` passed to the `inflate` handled most of it but I have a feeling maybe some of my ad networks don't do that. That is my only explanation at this time. – casolorz Nov 20 '17 at 16:43

0 Answers0