Skip to content

Crash when adding multiple attachments to Deck card – IllegalStateException: Two different ViewHolders have the same stable ID #1786

@meeoeen

Description

@meeoeen

This issue respects the following points:

Describe the bug

Hi 👋

A user of the Nextcloud Deck Android app is experiencing a crash when adding multiple attachments (images) to a card.

Context: The crash occurs immediately after adding the attachments to a Deck card. It seems that multiple items in the RecyclerView are assigned the same ID (-1), which leads to a collision and a crash.

Steps to reproduce:

  1. Open/create a card
  2. Click on Attachments tab
  3. Click upload
  4. Select gallery
  5. Add multiple pictures (long click on one pic then short click on more pics)
  6. Validate
  7. The IllegalStateException is thrown
  8. Attachments are added randomly - sometimes the last selected picture is added twice, sometimes some of the attachments are missing.

Suggestion: Maybe ensure that each attachment item in the adapter (CardAttachmentAdapter) has a unique stable ID, even if it hasn't yet been persisted to the server.

Expected behavior

No exception is thrown, and each pic is added once and only once as attachment to the card.

Deck Android version

1.24.5 (F-Droid)

Deck server version

1.15.2

Nextcloud Android version

3.32.2

Nextcloud version

31.0.7

Device

Samsung Galaxy S10+ (SM-G975U1)

Android Version

12

App Store

  • Google Play Store
  • Google Play Store (Beta channel)
  • F-Droid
  • Huawei App Gallery

Stacktrace

Full Crash:

App Version: 1.24.5
App Version Code: 1024005
App Flavor: fdroid

Files App Version Code: 30320290 ([com.nextcloud.android.sso.model.FilesAppType@dcba210](mailto:com.nextcloud.android.sso.model.FilesAppType@dcba210))

---

OS Version: 4.14.190-25741239-abG975U1UEU9IXE1(G975U1UEU9IXE1)
OS API Level: 31
Device: beyond2q
Manufacturer: samsung
Model (and Product): SM-G975U1 (beyond2qlteue)

---

java.lang.IllegalStateException: Two different ViewHolders have the same stable ID. Stable IDs in your adapter MUST BE unique and SHOULD NOT change.
 ViewHolder 1:ImageAttachmentViewHolder{241323 position=1 id=-1, oldPos=-1, pLpos:-1 not recyclable(1)} 
 View Holder 2:ImageAttachmentViewHolder{68f5452 position=0 id=-1, oldPos=-1, pLpos:-1} androidx.recyclerview.widget.RecyclerView{450131a VFED.V... ......ID 0,0-1080,1718 #7f0a0083 app:id/attachments_list}, adapter:it.niedermann.nextcloud.deck.ui.card.attachments.CardAttachmentAdapter@3c4e96b, layout:androidx.recyclerview.widget.GridLayoutManager@db82cc8, context:it.niedermann.nextcloud.deck.ui.card.EditActivity@738a980
at androidx.recyclerview.widget.RecyclerView.handleMissingPreInfoForChangeError(RecyclerView.java:4268)
at androidx.recyclerview.widget.RecyclerView.dispatchLayoutStep3(RecyclerView.java:4192)
at androidx.recyclerview.widget.RecyclerView.dispatchLayout(RecyclerView.java:3862)
at androidx.recyclerview.widget.RecyclerView.onLayout(RecyclerView.java:4404)
at android.view.View.layout(View.java:24461)
at android.view.ViewGroup.layout(ViewGroup.java:7412)
at androidx.coordinatorlayout.widget.CoordinatorLayout.layoutChild(CoordinatorLayout.java:1213)
at androidx.coordinatorlayout.widget.CoordinatorLayout.onLayoutChild(CoordinatorLayout.java:899)
at androidx.coordinatorlayout.widget.CoordinatorLayout.onLayout(CoordinatorLayout.java:919)
at android.view.View.layout(View.java:24461)
at android.view.ViewGroup.layout(ViewGroup.java:7412)
at android.widget.FrameLayout.layoutChildren(FrameLayout.java:374)
at android.widget.FrameLayout.onLayout(FrameLayout.java:312)
at android.view.View.layout(View.java:24461)
at android.view.ViewGroup.layout(ViewGroup.java:7412)
at androidx.recyclerview.widget.RecyclerView$LayoutManager.layoutDecoratedWithMargins(RecyclerView.java:9587)
at androidx.recyclerview.widget.LinearLayoutManager.layoutChunk(LinearLayoutManager.java:1685)
at androidx.recyclerview.widget.LinearLayoutManager.fill(LinearLayoutManager.java:1587)
at androidx.recyclerview.widget.LinearLayoutManager.onLayoutChildren(LinearLayoutManager.java:665)
at androidx.recyclerview.widget.RecyclerView.dispatchLayoutStep2(RecyclerView.java:4134)
at androidx.recyclerview.widget.RecyclerView.dispatchLayout(RecyclerView.java:3851)
at androidx.recyclerview.widget.RecyclerView.onLayout(RecyclerView.java:4404)
at android.view.View.layout(View.java:24461)
at android.view.ViewGroup.layout(ViewGroup.java:7412)
at androidx.viewpager2.widget.ViewPager2.onLayout(ViewPager2.java:527)
at android.view.View.layout(View.java:24461)
at android.view.ViewGroup.layout(ViewGroup.java:7412)
at com.google.android.material.appbar.HeaderScrollingViewBehavior.layoutChild(HeaderScrollingViewBehavior.java:149)
at com.google.android.material.appbar.ViewOffsetBehavior.onLayoutChild(ViewOffsetBehavior.java:43)
at com.google.android.material.appbar.AppBarLayout$ScrollingViewBehavior.onLayoutChild(AppBarLayout.java:2365)
at androidx.coordinatorlayout.widget.CoordinatorLayout.onLayout(CoordinatorLayout.java:918)
at android.view.View.layout(View.java:24461)
at android.view.ViewGroup.layout(ViewGroup.java:7412)
at android.widget.FrameLayout.layoutChildren(FrameLayout.java:374)
at android.widget.FrameLayout.onLayout(FrameLayout.java:312)
at android.view.View.layout(View.java:24461)
at android.view.ViewGroup.layout(ViewGroup.java:7412)
at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1829)
at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1673)
at android.widget.LinearLayout.onLayout(LinearLayout.java:1582)
at android.view.View.layout(View.java:24461)
at android.view.ViewGroup.layout(ViewGroup.java:7412)
at android.widget.FrameLayout.layoutChildren(FrameLayout.java:374)
at android.widget.FrameLayout.onLayout(FrameLayout.java:312)
at android.view.View.layout(View.java:24461)
at android.view.ViewGroup.layout(ViewGroup.java:7412)
at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1829)
at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1673)
at android.widget.LinearLayout.onLayout(LinearLayout.java:1582)
at android.view.View.layout(View.java:24461)
at android.view.ViewGroup.layout(ViewGroup.java:7412)
at android.widget.FrameLayout.layoutChildren(FrameLayout.java:374)
at android.widget.FrameLayout.onLayout(FrameLayout.java:312)
at com.android.internal.policy.DecorView.onLayout(DecorView.java:1330)
at android.view.View.layout(View.java:24461)
at android.view.ViewGroup.layout(ViewGroup.java:7412)
at android.view.ViewRootImpl.performLayout(ViewRootImpl.java:4609)
at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:4031)
at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:2919)
at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:10491)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:1108)
at android.view.Choreographer.doCallbacks(Choreographer.java:866)
at android.view.Choreographer.doFrame(Choreographer.java:797)
at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:1092)
at android.os.Handler.handleCallback(Handler.java:938)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loopOnce(Looper.java:226)
at android.os.Looper.loop(Looper.java:313)
at android.app.ActivityThread.main(ActivityThread.java:8663)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:567)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1135)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions