From 7c9282f3067b436ac58daa748c23b9732af2d36f Mon Sep 17 00:00:00 2001 From: Lukas Barth Date: Fri, 7 Mar 2014 00:58:26 +0100 Subject: [PATCH] Cache circle cropped photos on Recipient. --- .../securesms/ConversationItem.java | 5 ++- .../securesms/ConversationListItem.java | 5 +-- .../contacts/ContactPhotoFactory.java | 26 ++++++++++++- .../securesms/recipients/Recipient.java | 28 +++++++++----- .../recipients/RecipientProvider.java | 38 ++++++++++++------- 5 files changed, 72 insertions(+), 30 deletions(-) diff --git a/src/org/thoughtcrime/securesms/ConversationItem.java b/src/org/thoughtcrime/securesms/ConversationItem.java index 3e33e3bfd7..1cc76ff823 100644 --- a/src/org/thoughtcrime/securesms/ConversationItem.java +++ b/src/org/thoughtcrime/securesms/ConversationItem.java @@ -52,7 +52,6 @@ import org.thoughtcrime.securesms.mms.Slide; import org.thoughtcrime.securesms.mms.SlideDeck; import org.thoughtcrime.securesms.recipients.Recipient; import org.thoughtcrime.securesms.service.SendReceiveService; -import org.thoughtcrime.securesms.util.BitmapUtil; import org.thoughtcrime.securesms.util.DateUtils; import org.thoughtcrime.securesms.util.Emoji; import org.thoughtcrime.securesms.util.Dialogs; @@ -405,7 +404,9 @@ public class ConversationItem extends LinearLayout { private void setContactPhotoForRecipient(final Recipient recipient) { if (contactPhoto == null) return; - contactPhoto.setImageBitmap(BitmapUtil.getCircleCroppedBitmap(recipient.getContactPhoto())); + + contactPhoto.setImageBitmap(recipient.getCircleCroppedContactPhoto()); + contactPhoto.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { diff --git a/src/org/thoughtcrime/securesms/ConversationListItem.java b/src/org/thoughtcrime/securesms/ConversationListItem.java index 9694c25e6d..bdd10a9d93 100644 --- a/src/org/thoughtcrime/securesms/ConversationListItem.java +++ b/src/org/thoughtcrime/securesms/ConversationListItem.java @@ -30,7 +30,6 @@ import android.text.SpannableStringBuilder; import android.text.TextUtils; import android.text.style.StyleSpan; import android.util.AttributeSet; -import android.util.Log; import android.view.View; import android.widget.ImageView; import android.widget.RelativeLayout; @@ -39,7 +38,6 @@ import android.widget.TextView; import org.thoughtcrime.securesms.database.model.ThreadRecord; import org.thoughtcrime.securesms.recipients.Recipient; import org.thoughtcrime.securesms.recipients.Recipients; -import org.thoughtcrime.securesms.util.BitmapUtil; import org.thoughtcrime.securesms.util.DateUtils; import org.thoughtcrime.securesms.util.Emoji; @@ -131,7 +129,8 @@ public class ConversationListItem extends RelativeLayout private void setContactPhoto(final Recipient recipient) { if (recipient == null) return; - contactPhotoImage.setImageBitmap(BitmapUtil.getCircleCroppedBitmap(recipient.getContactPhoto())); + contactPhotoImage.setImageBitmap(recipient.getCircleCroppedContactPhoto()); + if (!recipient.isGroupRecipient()) { contactPhotoImage.setOnClickListener(new View.OnClickListener() { @Override diff --git a/src/org/thoughtcrime/securesms/contacts/ContactPhotoFactory.java b/src/org/thoughtcrime/securesms/contacts/ContactPhotoFactory.java index 763d9f0a03..c7c3dd824c 100644 --- a/src/org/thoughtcrime/securesms/contacts/ContactPhotoFactory.java +++ b/src/org/thoughtcrime/securesms/contacts/ContactPhotoFactory.java @@ -19,11 +19,15 @@ import java.util.Map; public class ContactPhotoFactory { - private static final Object defaultPhotoLock = new Object(); - private static final Object defaultGroupPhotoLock = new Object(); + private static final Object defaultPhotoLock = new Object(); + private static final Object defaultGroupPhotoLock = new Object(); + private static final Object defaultPhotoCroppedLock = new Object(); + private static final Object defaultGroupPhotoCroppedLock = new Object(); private static Bitmap defaultContactPhoto; private static Bitmap defaultGroupContactPhoto; + private static Bitmap defaultContactPhotoCropped; + private static Bitmap defaultGroupContactPhotoCropped; private static final Map localUserContactPhotoCache = Collections.synchronizedMap(new LRUCache(2)); @@ -52,6 +56,24 @@ public class ContactPhotoFactory { } } + public static Bitmap getDefaultContactPhotoCropped(Context context) { + synchronized (defaultPhotoCroppedLock) { + if (defaultContactPhotoCropped == null) + defaultContactPhotoCropped = BitmapUtil.getCircleCroppedBitmap(getDefaultContactPhoto(context)); + + return defaultContactPhotoCropped; + } + } + + public static Bitmap getDefaultGroupPhotoCropped(Context context) { + synchronized (defaultGroupPhotoCroppedLock) { + if (defaultGroupContactPhotoCropped == null) + defaultGroupContactPhotoCropped = BitmapUtil.getCircleCroppedBitmap(getDefaultGroupPhoto(context)); + + return defaultGroupContactPhotoCropped; + } + } + public static Bitmap getLocalUserContactPhoto(Context context, Uri uri) { if (uri == null) return getDefaultContactPhoto(context); diff --git a/src/org/thoughtcrime/securesms/recipients/Recipient.java b/src/org/thoughtcrime/securesms/recipients/Recipient.java index 7e05a47072..b7d29424c2 100644 --- a/src/org/thoughtcrime/securesms/recipients/Recipient.java +++ b/src/org/thoughtcrime/securesms/recipients/Recipient.java @@ -25,6 +25,7 @@ import android.util.Log; import org.thoughtcrime.securesms.contacts.ContactPhotoFactory; import org.thoughtcrime.securesms.recipients.RecipientProvider.RecipientDetails; +import org.thoughtcrime.securesms.util.BitmapUtil; import org.thoughtcrime.securesms.util.GroupUtil; import org.whispersystems.textsecure.storage.CanonicalRecipient; import org.whispersystems.textsecure.util.FutureTaskListener; @@ -52,15 +53,19 @@ public class Recipient implements Parcelable, CanonicalRecipient { private final long recipientId; private String name; + private Bitmap contactPhoto; + private Bitmap circleCroppedContactPhoto; + private Uri contactUri; - Recipient(String number, Bitmap contactPhoto, long recipientId, - ListenableFutureTask future) + Recipient(String number, Bitmap contactPhoto, Bitmap circleCroppedContactPhoto, + long recipientId, ListenableFutureTask future) { - this.number = number; - this.contactPhoto = contactPhoto; - this.recipientId = recipientId; + this.number = number; + this.circleCroppedContactPhoto = circleCroppedContactPhoto; + this.contactPhoto = contactPhoto; + this.recipientId = recipientId; future.setListener(new FutureTaskListener() { @Override @@ -69,10 +74,11 @@ public class Recipient implements Parcelable, CanonicalRecipient { HashSet localListeners; synchronized (Recipient.this) { - Recipient.this.name = result.name; - Recipient.this.contactUri = result.contactUri; - Recipient.this.contactPhoto = result.avatar; - localListeners = (HashSet)listeners.clone(); + Recipient.this.name = result.name; + Recipient.this.contactUri = result.contactUri; + Recipient.this.contactPhoto = result.avatar; + Recipient.this.circleCroppedContactPhoto = result.croppedAvatar; + localListeners = (HashSet) listeners.clone(); listeners.clear(); } @@ -174,6 +180,10 @@ public class Recipient implements Parcelable, CanonicalRecipient { return contactPhoto; } + public synchronized Bitmap getCircleCroppedContactPhoto() { + return this.circleCroppedContactPhoto; + } + public static Recipient getUnknownRecipient(Context context) { return new Recipient("Unknown", "Unknown", -1, null, ContactPhotoFactory.getDefaultContactPhoto(context)); } diff --git a/src/org/thoughtcrime/securesms/recipients/RecipientProvider.java b/src/org/thoughtcrime/securesms/recipients/RecipientProvider.java index 15701641e8..725bd7ece7 100644 --- a/src/org/thoughtcrime/securesms/recipients/RecipientProvider.java +++ b/src/org/thoughtcrime/securesms/recipients/RecipientProvider.java @@ -21,7 +21,6 @@ import android.database.Cursor; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.net.Uri; -import android.provider.ContactsContract; import android.provider.ContactsContract.Contacts; import android.provider.ContactsContract.PhoneLookup; import android.util.Log; @@ -30,13 +29,13 @@ import org.thoughtcrime.securesms.contacts.ContactPhotoFactory; import org.thoughtcrime.securesms.database.CanonicalAddressDatabase; import org.thoughtcrime.securesms.database.DatabaseFactory; import org.thoughtcrime.securesms.database.GroupDatabase; +import org.thoughtcrime.securesms.util.BitmapUtil; import org.thoughtcrime.securesms.util.GroupUtil; import org.thoughtcrime.securesms.util.LRUCache; -import org.whispersystems.textsecure.util.ListenableFutureTask; import org.thoughtcrime.securesms.util.Util; +import org.whispersystems.textsecure.util.ListenableFutureTask; import java.io.IOException; -import java.io.InputStream; import java.util.Collections; import java.util.Map; import java.util.concurrent.Callable; @@ -103,10 +102,18 @@ public class RecipientProvider { asyncRecipientResolver.submit(future); - final Bitmap defaultPhoto = isGroupRecipient - ? ContactPhotoFactory.getDefaultGroupPhoto(context) - : ContactPhotoFactory.getDefaultContactPhoto(context); - Recipient recipient = new Recipient(number, defaultPhoto, recipientId, future); + Bitmap contactPhoto; + Bitmap contactPhotoCropped; + + if (isGroupRecipient) { + contactPhoto = ContactPhotoFactory.getDefaultGroupPhoto(context); + contactPhotoCropped = ContactPhotoFactory.getDefaultGroupPhotoCropped(context); + } else { + contactPhoto = ContactPhotoFactory.getDefaultContactPhoto(context); + contactPhotoCropped = ContactPhotoFactory.getDefaultContactPhotoCropped(context); + } + + Recipient recipient = new Recipient(number, contactPhoto, contactPhotoCropped, recipientId, future); recipientCache.put(recipientId, recipient); return recipient; @@ -132,7 +139,8 @@ public class RecipientProvider { Bitmap contactPhoto = ContactPhotoFactory.getContactPhoto(context, Uri.withAppendedPath(Contacts.CONTENT_URI, cursor.getLong(2)+"")); - return new RecipientDetails(cursor.getString(0), contactUri, contactPhoto); + return new RecipientDetails(cursor.getString(0), contactUri, contactPhoto, + BitmapUtil.getCircleCroppedBitmap(contactPhoto)); } } finally { if (cursor != null) @@ -154,7 +162,7 @@ public class RecipientProvider { if (avatarBytes == null) avatar = ContactPhotoFactory.getDefaultGroupPhoto(context); else avatar = BitmapFactory.decodeByteArray(avatarBytes, 0, avatarBytes.length); - return new RecipientDetails(record.getTitle(), null, avatar); + return new RecipientDetails(record.getTitle(), null, avatar, BitmapUtil.getCircleCroppedBitmap(avatar)); } return null; @@ -167,12 +175,14 @@ public class RecipientProvider { public static class RecipientDetails { public final String name; public final Bitmap avatar; - public final Uri contactUri; + public final Bitmap croppedAvatar; + public final Uri contactUri; - public RecipientDetails(String name, Uri contactUri, Bitmap avatar) { - this.name = name; - this.avatar = avatar; - this.contactUri = contactUri; + public RecipientDetails(String name, Uri contactUri, Bitmap avatar, Bitmap croppedAvatar) { + this.name = name; + this.avatar = avatar; + this.croppedAvatar = croppedAvatar; + this.contactUri = contactUri; } }