google / flexbox-layout

Flexbox for Android
Apache License 2.0
18.21k stars 1.79k forks source link

RecyclerView crashing in some circumstances #240

Open donpwilson opened 7 years ago

donpwilson commented 7 years ago

I have been experimenting with "com.google.android:flexbox:0.3.0-alpha2" with a view to adding it to my photo app as an alternative way of displaying photos. I appreciate that this version is not yet fully stable.

I experience a crash in certain circumstances and report it here in the hope that your testing / debugging can resolve it.

I display a grid of photos and have buttons that enable the user to zoom in or out of the grid. These vary to height of each row. I get a crash on zoom in when the bottom photos are pushed out of view. I'm thinking that there is a confusion between being detached and being recycled. This crash also follows a warning message from View's requestLayout(). Here's the log:


03-29 11:47:42.833 21953-21953/com.dpw.photoplayer W/View: requestLayout() improperly called by android.support.v7.widget.AppCompatTextView{3c009ebc V.ED..C. ......ID 6,306-359,363 #7f100199 app:id/photo_text} during layout: running second layout pass
03-29 11:47:42.833 21953-21953/com.dpw.photoplayer W/View: requestLayout() improperly called by android.support.v7.widget.AppCompatTextView{3e090e45 V.ED.... ......ID 170,6-194,63 #7f100197 app:id/photo_count} during layout: running second layout pass
03-29 11:47:42.833 21953-21953/com.dpw.photoplayer W/View: requestLayout() improperly called by android.support.v7.widget.AppCompatImageView{3a92499a V.ED.... ......ID 6,6-552,366 #7f100193 app:id/photo_image} during layout: running second layout pass
03-29 11:47:42.833 21953-21953/com.dpw.photoplayer W/View: requestLayout() improperly called by android.support.v7.widget.AppCompatTextView{9d272cb V.ED..C. ......ID 110,306-448,363 #7f100199 app:id/photo_text} during layout: running second layout pass
03-29 11:47:42.833 21953-21953/com.dpw.photoplayer W/View: requestLayout() improperly called by android.support.v7.widget.AppCompatTextView{2196eaa8 V.ED.... ......ID 267,6-291,63 #7f100197 app:id/photo_count} during layout: running second layout pass
03-29 11:47:42.979 21953-21953/com.dpw.photoplayer E/AndroidRuntime: FATAL EXCEPTION: main
                                                                     Process: com.dpw.photoplayer, PID: 21953
                                                                     java.lang.IllegalArgumentException: Tmp detached view should be removed from RecyclerView before it can be recycled: ViewHolder{11587ca3 position=3 id=-776809114, oldPos=-1, pLpos:-1 tmpDetached no parent}
                                                                         at android.support.v7.widget.RecyclerView$Recycler.recycleViewHolderInternal(RecyclerView.java:5692)
                                                                         at android.support.v7.widget.RecyclerView.removeAnimatingView(RecyclerView.java:1279)
                                                                         at android.support.v7.widget.RecyclerView$ItemAnimatorRestoreListener.onAnimationFinished(RecyclerView.java:11518)
                                                                         at android.support.v7.widget.RecyclerView$ItemAnimator.dispatchAnimationFinished(RecyclerView.java:12018)
                                                                         at android.support.v7.widget.SimpleItemAnimator.dispatchRemoveFinished(SimpleItemAnimator.java:265)
                                                                         at android.support.v7.widget.DefaultItemAnimator$4.onAnimationEnd(DefaultItemAnimator.java:209)
                                                                         at android.support.v4.view.ViewPropertyAnimatorCompatJB$1.onAnimationEnd(ViewPropertyAnimatorCompatJB.java:51)
                                                                         at android.view.ViewPropertyAnimator$AnimatorEventListener.onAnimationEnd(ViewPropertyAnimator.java:1116)
                                                                         at android.animation.ValueAnimator.endAnimation(ValueAnimator.java:1171)
                                                                         at android.animation.ValueAnimator$AnimationHandler.doAnimationFrame(ValueAnimator.java:722)
                                                                         at android.animation.ValueAnimator$AnimationHandler.run(ValueAnimator.java:738)
                                                                         at android.view.Choreographer$CallbackRecord.run(Choreographer.java:767)
                                                                         at android.view.Choreographer.doCallbacks(Choreographer.java:580)
                                                                         at android.view.Choreographer.doFrame(Choreographer.java:549)
                                                                         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:5254)
                                                                         at java.lang.reflect.Method.invoke(Native Method)
                                                                         at java.lang.reflect.Method.invoke(Method.java:372)
                                                                         at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:903)
                                                                         at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:698)
`
thagikura commented 7 years ago

Thanks for reporting!

Is it possible to share your piece of code that may be relevant to reproduce it?

donpwilson commented 7 years ago

Here's what I hope is the most relevant code. My adapter is full of what I think is irrelevant code so I have cut it down below to what I think is relevant. I've also cut down the photo_item layout substantially. You will see that I set the size of each photo in the imageView so that its height matches the grid side and its width respects its aspect ratio. I should perhaps add that I don't have any issues with the other layout managers. I hope this helps:

Code to initialize:

   private void setGridLayoutManager() {
        int type = My_Preferences.getInstance().getGridLayout();
        switch (type) {
            case 0:
                pGridLayoutManager = new StaggeredGridLayoutManager(2, GridLayoutManager.VERTICAL);
                pCurrentLayoutManagerType = GRID_TYPE.STAGGERED_GRID;
                break;
            case 1:
                pGridLayoutManager = new GridLayoutManager(getActivity(), 2, GridLayoutManager.VERTICAL, false);
                pCurrentLayoutManagerType = VERTICAL_LINEAR_GRID;
                break;
            case 2:
                pGridLayoutManager = new GridLayoutManager(getActivity(), 2, GridLayoutManager.VERTICAL, false);
                pCurrentLayoutManagerType = VERTICAL_GRID_OF_SQUARES;
                break;
            case 3:
                FlexboxLayoutManager layoutManager = new FlexboxLayoutManager();
                layoutManager.setFlexWrap(FlexWrap.WRAP);
                layoutManager.setFlexDirection(FlexDirection.ROW);
                layoutManager.setAlignItems(AlignItems.STRETCH);
                layoutManager.setJustifyContent(JustifyContent.CENTER);
                pGridLayoutManager = layoutManager;
                pCurrentLayoutManagerType = VERTICAL_FILLED_ROWS;
                break;
            default:
                pGridLayoutManager = new GridLayoutManager(getActivity(), 2, GridLayoutManager.VERTICAL, false);
                pCurrentLayoutManagerType = VERTICAL_LINEAR_GRID;
                break;
        }
        pGridGallery.setLayoutManager(pGridLayoutManager);
    }

Code to reset grid side:

pAdapter.setGridSide(grid_side);

Cut down adapter:

class Adapter_Photo_Album_Copy extends RecyclerView.Adapter<Adapter_Photo_Album_Copy.ViewHolder> {

    private Fragment_Photo_Album.GRID_TYPE pLayoutType;
    private int pGridSide;

    @Override
    public int getItemCount() {
        return ....
    }

    Photo_Record getItem(final int position) {
        Photo_Record record = null;
        return....
    }

    void setGridSide(final int side) {
        if (side != pGridSide) {
            pGridSide = side;
            if (getItemCount() > 0) {
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        notifyItemRangeChanged(0, getItemCount());
                    }
                });
            }
        }
    }

    @Override
    public ViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) {
        View v = LayoutInflater.from(viewGroup.getContext())
                .inflate(R.layout.photo_item, viewGroup, false);
        return new ViewHolder(v);
    }

    @Override
    public void onBindViewHolder(final ViewHolder viewHolder, final int position) {
        if (position != RecyclerView.NO_POSITION) {
            final Photo_Record photo_record = getItem(position);
            if (photo_record != null) {
                final Source_Record source_record = photo_record.getSourceRecord();
                if (source_record != null) {
                    final String photo = photo_record.getPhoto();
                    Point dimensions = photo_record.getDimensionsAdjustedForOrientation();
                    int grid_item_height;
                    int grid_item_width;
                    FrameLayout.LayoutParams params = (FrameLayout.LayoutParams) viewHolder.getImageView().getLayoutParams();
                    if (pLayoutType == Fragment_Photo_Album.GRID_TYPE.HORIZONTAL_SINGLE_ROW) {
                        //....
                    } else if (pLayoutType == Fragment_Photo_Album.GRID_TYPE.VERTICAL_FILLED_ROWS) {
                        grid_item_height = pGridSide;
                        // adjusts for borders
                        grid_item_width = (int) ((double) (grid_item_height - My_Utils.dpToPx(2)) * (double) dimensions.x /
                                (double) dimensions.y) + My_Utils.dpToPx(2);
                    } else {
                        //....
                    }
                    params.width = grid_item_width;
                    params.height = grid_item_height;
                    viewHolder.getImageView().setLayoutParams(params);
                    if (pLayoutType == Fragment_Photo_Album.GRID_TYPE.VERTICAL_GRID_OF_SQUARES) {
                        viewHolder.getImageView().setScaleType(ImageView.ScaleType.CENTER_CROP);
                    } else {
                        viewHolder.getImageView().setScaleType(ImageView.ScaleType.FIT_CENTER);
                    }
                    if ((grid_item_width > My_Utils.dpToPx(2)) && (grid_item_height > My_Utils.dpToPx(2))) {
                        //......
                    }
                }
            }
        }
    }

    class ViewHolder extends RecyclerView.ViewHolder {
        private final LinearLayout layout;
        private final ImageView imageView;

        ViewHolder(View v) {
            super(v);
            layout = (LinearLayout) v.findViewById(R.id.photo_item);
            imageView = (ImageView) v.findViewById(R.id.photo_image);
        }

        LinearLayout getLayoutView() {
            return layout;
        }

        ImageView getImageView() {
            return imageView;
        }
    }
}

Layout:

<LinearLayout
    android:id="@+id/photo_item"
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_gravity="center"
    android:gravity="center"
    android:orientation="horizontal">

    <FrameLayout
        android:id="@+id/photo_border"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="@drawable/photo_background">

        <ImageView
            android:id="@+id/photo_image"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:adjustViewBounds="true"
            android:contentDescription="@string/app_name"
            android:gravity="center"
            android:scaleType="fitCenter"/>

  </FrameLayout>

</LinearLayout>
thagikura commented 7 years ago

Thanks for pasting the code.

How do you zoom in the RecyclerView when the button is clicked?

donpwilson commented 7 years ago

I just calculate a new value and feed it to the adapter through setGridSide(). As you can see above this runs notifyItemRangeChanged() on all the items in the adapter. onBindViewHolder() then picks up the revised height and recalculates the size of each photo.

thagikura commented 7 years ago

Sorry for the delayed reply.

I couldn't still figure out the root cause of this issue. By any chance is it possible to create a sample project that I can build and debug?

Also there is a new version of 0.3.0-alpha3 with bunch of bug fixes. So it doesn't hurt if you can try it and see if it's fixed.

Thanks.

donpwilson commented 7 years ago

I've already tried 0.3.0-alpha3 and the problem still exists.

It might take me a little while but I'll try to set something up, maybe using your cats sample app as a base.

thagikura commented 7 years ago

Thanks. Really appreciate it.

donpwilson commented 7 years ago

I've set up zoom in / out on the cats sample ad it worked fine. So I looked harder at the crash. I noticed that it appears to be to do with the animation of views, specifically as they are removed from view. I switched off this animation in my app and it no longer crashes. However it then does not properly refresh until I scroll up or down.

I tried to clear animations on view detach from window but with no effect. See http://stackoverflow.com/questions/26724964/how-to-animate-recyclerview-items-when-they-appear

Does this help at all?

thagikura commented 7 years ago

Thanks! It's very helpful. Is it possible to see your forked version of the cat demo app? I'd like to try and see the code 👍

donpwilson commented 7 years ago

How best can I send you the code. Email the zipped file? Or, I've never used gist but you could start me off?

thagikura commented 7 years ago

Sure, either of creating a GitHub repository, or attaching a zipped file to this issue are convenient to see the file. Thanks in advance :)

donpwilson commented 7 years ago

Here's a zipped file. You will find that I haven't changed very much. Feel free to incorporate in an enhanced demo if you wish. demo-cat-gallery.zip

thagikura commented 7 years ago

Thank you! I was able to launch the app, but what operations are needed to reproduce? I tried several operations including "zoom in" and "zoom out" including pushing the bottom image out of the boundary by tapping "zoom in", but couldn't reproduce it so far.

donpwilson commented 7 years ago

Sorry about the confusion. The cat app doesn't crash. When I said that I looked further at the crash I meant the crash in my app - I included the logcat at the top of this correspondence where you can see how it appears to be related to the animation of views.

thagikura commented 7 years ago

Okay, so is it possible to see your app code in a way I can debug by any chance? It's really hard to debug from only the Logcat for this issue.

donpwilson commented 7 years ago

I appreciate the difficulty. However, I have some good news. I have been continuing to investigate and experiment and have found a way to avoid crashes. To make sure that I get the animations I was using: notifyItemRangeChanged(0, getItemCount()) but have changed to use: notifyDataSetChanged() My app no longer crashes on zoom in, presumably because the way that changes are processed is different. I still get animated changes because I have set: setHasStableIds(true) I still think there is an issue somewhere because I still get the: requestLayout() improperly called message.

In my researches I came across the following where another recyclerView layout manager developer was experiencing a similar issue. It's possible, if you haven't seen it before, that the discussion may give you some pointers. https://issuetracker.google.com/issues/37098293

I would be happy to let you have access to my app code but in view of the above I suggest the following.

  1. Close this issue
  2. You continue with your other testing to production
  3. If you then find at some stage that others are finding the same or a similar problem, you come back to me and I'll get my code to you.

How does that sound?

thagikura commented 7 years ago

Thanks for the pointer, it's really useful.

Just to make sure, if you use the built-in layout managers (such as LinearLayoutManager, StaggeredGridLayoutManager), the app doesn't crash, right?

If so, it's likely the issue is on FlexboxLayoutManager, so I want to keep this issue open. But given that there are other outstanding bugs and enhancements that are likely to be experienced/used more often, I'd choose the option 3.

donpwilson commented 7 years ago

Glad to be of help!

Yes, the built in layout managers do not crash and do not have the request layout warning.

Don't hesitate to come back to me if or when you want.

onlymash commented 5 years ago

same issue is here. https://github.com/onlymash/Flexbooru

2019-01-31 02:47:39.883 10254-10254/onlymash.flexbooru E/AndroidRuntime: FATAL EXCEPTION: main
    Process: onlymash.flexbooru, PID: 10254
    java.lang.IllegalArgumentException: Tmp detached view should be removed from RecyclerView before it can be recycled: ViewHolder{91a68b4 position=7 id=-1, oldPos=-1, pLpos:-1 tmpDetached no parent} androidx.recyclerview.widget.RecyclerView{c0a257e VFED.V... ........ 0,0-1080,1584 #7f08008c app:id/list}, adapter:onlymash.flexbooru.ui.adapter.PostDanAdapter@5328adf, layout:com.google.android.flexbox.FlexboxLayoutManager@44f432c, context:onlymash.flexbooru.ui.MainActivity@6dce1ec
        at androidx.recyclerview.widget.RecyclerView$Recycler.recycleViewHolderInternal(RecyclerView.java:6165)
        at androidx.recyclerview.widget.RecyclerView.removeAnimatingView(RecyclerView.java:1451)
        at androidx.recyclerview.widget.RecyclerView$ItemAnimatorRestoreListener.onAnimationFinished(RecyclerView.java:12454)
        at androidx.recyclerview.widget.RecyclerView$ItemAnimator.dispatchAnimationFinished(RecyclerView.java:12954)
        at androidx.recyclerview.widget.SimpleItemAnimator.dispatchRemoveFinished(SimpleItemAnimator.java:277)
        at androidx.recyclerview.widget.DefaultItemAnimator$4.onAnimationEnd(DefaultItemAnimator.java:213)
        at android.view.ViewPropertyAnimator$AnimatorEventListener.onAnimationEnd(ViewPropertyAnimator.java:1122)
        at android.animation.Animator$AnimatorListener.onAnimationEnd(Animator.java:552)
        at android.animation.ValueAnimator.endAnimation(ValueAnimator.java:1232)
        at android.animation.ValueAnimator.doAnimationFrame(ValueAnimator.java:1474)
        at android.animation.AnimationHandler.doAnimationFrame(AnimationHandler.java:146)
        at android.animation.AnimationHandler.access$100(AnimationHandler.java:37)
        at android.animation.AnimationHandler$1.doFrame(AnimationHandler.java:54)
        at android.view.Choreographer$CallbackRecord.run(Choreographer.java:947)
        at android.view.Choreographer.doCallbacks(Choreographer.java:761)
        at android.view.Choreographer.doFrame(Choreographer.java:693)
        at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:935)
        at android.os.Handler.handleCallback(Handler.java:873)
        at android.os.Handler.dispatchMessage(Handler.java:99)
        at android.os.Looper.loop(Looper.java:193)
        at android.app.ActivityThread.main(ActivityThread.java:6718)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)
private fun init() {
        postViewModel = getPostViewModel(app.serviceLocator.getRepository())
        glide = GlideApp.with(this)
        val flexboxLayoutManager = FlexboxLayoutManager(requireContext()).apply {
            flexWrap = FlexWrap.WRAP
            flexDirection = FlexDirection.ROW
            alignItems = AlignItems.STRETCH
        }
        list.layoutManager = flexboxLayoutManager
        list.addOnScrollListener(object : RecyclerView.OnScrollListener() {
            override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) {
                when (newState) {
                    RecyclerView.SCROLL_STATE_IDLE -> glide.resumeRequests()
                    else -> glide.pauseRequests()
                }
            }
        })
        initPostDanAdapter()
    }

    private fun initPostDanAdapter() {
        val postDanAdapter = PostDanAdapter(glide, requireActivity())
        list.adapter = postDanAdapter
        postViewModel.postsDan.observe(this, Observer<PagedList<PostDan>> { posts ->
            postDanAdapter.submitList(posts)
        })
        initSwipeToRefreshDan()
    }
class PostDanAdapter(private val glide: GlideRequests,
                     private val activity: Activity): PagedListAdapter<PostDan, RecyclerView.ViewHolder>(POST_COMPARATOR) {

    companion object {
        val POST_COMPARATOR = object : DiffUtil.ItemCallback<PostDan>() {
            override fun areContentsTheSame(oldItem: PostDan, newItem: PostDan): Boolean =
                oldItem == newItem
            override fun areItemsTheSame(oldItem: PostDan, newItem: PostDan): Boolean {
                return oldItem.id == newItem.id
            }
        }
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder =
        PostDanViewHolder.create(parent, glide, activity)

    override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
        (holder as PostDanViewHolder).bind(getItem(position))
    }
}
class PostDanViewHolder(itemView: View,
       private val glide: GlideRequests,
       private val activity: Activity): RecyclerView.ViewHolder(itemView){

    companion object {
        fun create(parent: ViewGroup, glide: GlideRequests, activity: Activity): PostDanViewHolder {
            val view = LayoutInflater.from(parent.context)
                .inflate(R.layout.post_item, parent, false)
            return PostDanViewHolder(view, glide, activity)
        }
    }

    private val preview: ImageView = itemView.findViewById(R.id.preview)
    private var postDan: PostDan? = null

    fun bind(post: PostDan?) {
        postDan = post
        if (post is PostDan && !post.preview_file_url.isNullOrEmpty()) {
            val lp = preview.layoutParams
            if (lp is FlexboxLayoutManager.LayoutParams) {
                lp.flexGrow = 1f
            }
            val placeholder = when (post.rating) {
                "s" -> R.drawable.background_rating_s
                "q" -> R.drawable.background_rating_q
                else -> R.drawable.background_rating_e
            }
            lp.width = lp.height * post.image_width/post.image_height
            glide.load(FlexGlideUrl(post.preview_file_url))
                .placeholder(activity.resources.getDrawable(placeholder, activity.theme))
                .centerCrop()
                .into(preview)
        }
    }
}
piotrkst commented 5 years ago

For me it does crash with androidx.recyclerview.widget.LinearLayoutManager.

In my case it has something to do with the combination of TransitionManager.beginDelayedTransition, adapter.setHasStableIds(true) and adapter.notifyDataSetChanged().

mattmikolay commented 3 years ago

I’m seeing this crash as well.

The crash does not occur for me if I use LinearLayoutManager , or if I disable item animations on the RecyclerView altogether using RecyclerView#setItemAnimator(null). Setting stable IDs did not help.

I'll add that I'm using a RecyclerView to display search results as the user types; the FlexboxLayoutManager here is constantly updating item views as new search results are returned.

java.lang.IllegalArgumentException: Tmp detached view should be removed from RecyclerView before it can be recycled: HeaderViewHolder{7c84648 position=22 id=-1, oldPos=-1, pLpos:-1 tmpDetached no parent} androidx.recyclerview.widget.RecyclerView{c92a72b VFED..... ......ID 0,0-1080,1337 #7f080163 app:id/sound_recycler}, adapter:com.testapp.android.ui.recycler.SearchResultsListAdapter@fa27788, layout:com.google.android.flexbox.FlexboxLayoutManager@3c88521, context:com.testapp.android.MainActivity@6a2f083
    at androidx.recyclerview.widget.RecyclerView$Recycler.recycleViewHolderInternal(RecyclerView.java:6439)
    at androidx.recyclerview.widget.RecyclerView.removeAnimatingView(RecyclerView.java:1456)
    at androidx.recyclerview.widget.RecyclerView$ItemAnimatorRestoreListener.onAnimationFinished(RecyclerView.java:12699)
    at androidx.recyclerview.widget.RecyclerView$ItemAnimator.dispatchAnimationFinished(RecyclerView.java:13199)
    at androidx.recyclerview.widget.SimpleItemAnimator.dispatchRemoveFinished(SimpleItemAnimator.java:277)
    at androidx.recyclerview.widget.DefaultItemAnimator$4.onAnimationEnd(DefaultItemAnimator.java:213)
    at android.view.ViewPropertyAnimator$AnimatorEventListener.onAnimationEnd(ViewPropertyAnimator.java:1111)
    at android.animation.Animator$AnimatorListener.onAnimationEnd(Animator.java:554)
    at android.animation.ValueAnimator.endAnimation(ValueAnimator.java:1242)
    at android.animation.ValueAnimator.doAnimationFrame(ValueAnimator.java:1484)
    at android.animation.AnimationHandler.doAnimationFrame(AnimationHandler.java:146)
    at android.animation.AnimationHandler.access$100(AnimationHandler.java:37)
    at android.animation.AnimationHandler$1.doFrame(AnimationHandler.java:54)
    at android.view.Choreographer$CallbackRecord.run(Choreographer.java:964)
    at android.view.Choreographer.doCallbacks(Choreographer.java:790)
    at android.view.Choreographer.doFrame(Choreographer.java:721)
    at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:951)
    at android.os.Handler.handleCallback(Handler.java:883)
    at android.os.Handler.dispatchMessage(Handler.java:100)
    at android.os.Looper.loop(Looper.java:214)
    at android.app.ActivityThread.main(ActivityThread.java:7356)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:930)
Neilcc commented 3 years ago

Do we have any solutions for this now?

marciogranzotto commented 2 years ago

Check if my fix helps: https://github.com/androidx/androidx/pull/252

zmunm commented 2 years ago

+1

abhimuktheeswarar commented 2 years ago

I'm using RecyclerView's ListAdapter (with DiffUtil). Setting recyclerView.itemAnimator = null solved the issue.

mtotschnig commented 1 month ago

I have received feedback from a user of my app that allows me to reproduce the problem. My app has a screen where user manages a list of tags. I use RecyclerView with FlexboxLayoutManager, layout horizontal and DiffUtil.ItemCallback. Tags are sorted alphabetically. When user edits a tag and it's new position was a place that's just around the end of the screen, app crashes.