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:
- Open/create a card
- Click on Attachments tab
- Click upload
- Select gallery
- Add multiple pictures (long click on one pic then short click on more pics)
- Validate
- The IllegalStateException is thrown
- 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
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)
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:
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
Stacktrace