From 4b5a95bff0cbdb961f4aa8a4744fe943da5fb7da Mon Sep 17 00:00:00 2001 From: Sylvia van Os Date: Sun, 16 Jun 2024 11:25:20 +0200 Subject: [PATCH] Load thumbnails on main screen asynchronously Decoding a bitmap can be slow. On slow devices, loading all the images as soon as the card should be shown can lead to UI freezes. By loading the thumbnail asynchronously, scrolling quickly remains smooth even on slow devices. --- .../card_locker/LoyaltyCardCursorAdapter.java | 31 ++++++++++++++----- 1 file changed, 24 insertions(+), 7 deletions(-) diff --git a/app/src/main/java/protect/card_locker/LoyaltyCardCursorAdapter.java b/app/src/main/java/protect/card_locker/LoyaltyCardCursorAdapter.java index 6b807b7ecc..d48ea96d56 100644 --- a/app/src/main/java/protect/card_locker/LoyaltyCardCursorAdapter.java +++ b/app/src/main/java/protect/card_locker/LoyaltyCardCursorAdapter.java @@ -6,6 +6,8 @@ import android.graphics.Bitmap; import android.graphics.Color; import android.graphics.drawable.Drawable; +import android.os.Handler; +import android.os.Looper; import android.util.SparseBooleanArray; import android.util.TypedValue; import android.view.HapticFeedbackConstants; @@ -88,9 +90,29 @@ public void onBindViewHolder(LoyaltyCardListItemViewHolder inputHolder, Cursor i inputHolder.mDivider.setVisibility(View.GONE); LoyaltyCard loyaltyCard = LoyaltyCard.toLoyaltyCard(inputCursor); - Bitmap icon = Utils.retrieveCardImage(mContext, loyaltyCard.id, ImageLocationType.icon); - if (mLoyaltyCardListDisplayOptions.showingNameBelowThumbnail() && icon != null) { + inputHolder.mCardIcon.setContentDescription(loyaltyCard.store); + + // Default header at first, real icon will be retrieved asynchronously if it exists to ensure + // smooth scrolling even on slower devices + Utils.setIconOrTextWithBackground(mContext, loyaltyCard, null, inputHolder.mCardIcon, inputHolder.mCardText); + inputHolder.toggleCardStateIcon(loyaltyCard.starStatus != 0, loyaltyCard.archiveStatus != 0, itemSelected(inputCursor.getPosition())); + boolean hasIcon = Utils.retrieveCardImageAsFile(mContext, loyaltyCard.id, ImageLocationType.icon).exists(); + if (hasIcon) { + new Thread() { + @Override + public void run() { + Bitmap icon = Utils.retrieveCardImage(mContext, loyaltyCard.id, ImageLocationType.icon); + + new Handler(Looper.getMainLooper()).post(() -> { + inputHolder.mIconBackgroundColor = Utils.setIconOrTextWithBackground(mContext, loyaltyCard, icon, inputHolder.mCardIcon, inputHolder.mCardText); + inputHolder.toggleCardStateIcon(loyaltyCard.starStatus != 0, loyaltyCard.archiveStatus != 0, itemSelected(inputHolder.getAdapterPosition())); + }); + } + }.start(); + } + + if (mLoyaltyCardListDisplayOptions.showingNameBelowThumbnail() && hasIcon) { showDivider = true; inputHolder.setStoreField(loyaltyCard.store); } else { @@ -122,11 +144,6 @@ public void onBindViewHolder(LoyaltyCardListItemViewHolder inputHolder, Cursor i inputHolder.setExtraField(inputHolder.mExpiryField, null, null, false); } - inputHolder.mCardIcon.setContentDescription(loyaltyCard.store); - inputHolder.mIconBackgroundColor = Utils.setIconOrTextWithBackground(mContext, loyaltyCard, icon, inputHolder.mCardIcon, inputHolder.mCardText); - - inputHolder.toggleCardStateIcon(loyaltyCard.starStatus != 0, loyaltyCard.archiveStatus != 0, itemSelected(inputCursor.getPosition())); - inputHolder.itemView.setActivated(mSelectedItems.get(inputCursor.getPosition(), false)); applyIconAnimation(inputHolder, inputCursor.getPosition()); applyClickEvents(inputHolder, inputCursor.getPosition());