Cache circle cropped photos on Recipient.

This commit is contained in:
Lukas Barth 2014-03-07 00:58:26 +01:00 committed by Moxie Marlinspike
parent fa3cb871d0
commit 7c9282f306
5 changed files with 72 additions and 30 deletions

View File

@ -52,7 +52,6 @@ import org.thoughtcrime.securesms.mms.Slide;
import org.thoughtcrime.securesms.mms.SlideDeck; import org.thoughtcrime.securesms.mms.SlideDeck;
import org.thoughtcrime.securesms.recipients.Recipient; import org.thoughtcrime.securesms.recipients.Recipient;
import org.thoughtcrime.securesms.service.SendReceiveService; import org.thoughtcrime.securesms.service.SendReceiveService;
import org.thoughtcrime.securesms.util.BitmapUtil;
import org.thoughtcrime.securesms.util.DateUtils; import org.thoughtcrime.securesms.util.DateUtils;
import org.thoughtcrime.securesms.util.Emoji; import org.thoughtcrime.securesms.util.Emoji;
import org.thoughtcrime.securesms.util.Dialogs; import org.thoughtcrime.securesms.util.Dialogs;
@ -405,7 +404,9 @@ public class ConversationItem extends LinearLayout {
private void setContactPhotoForRecipient(final Recipient recipient) { private void setContactPhotoForRecipient(final Recipient recipient) {
if (contactPhoto == null) return; if (contactPhoto == null) return;
contactPhoto.setImageBitmap(BitmapUtil.getCircleCroppedBitmap(recipient.getContactPhoto()));
contactPhoto.setImageBitmap(recipient.getCircleCroppedContactPhoto());
contactPhoto.setOnClickListener(new View.OnClickListener() { contactPhoto.setOnClickListener(new View.OnClickListener() {
@Override @Override
public void onClick(View v) { public void onClick(View v) {

View File

@ -30,7 +30,6 @@ import android.text.SpannableStringBuilder;
import android.text.TextUtils; import android.text.TextUtils;
import android.text.style.StyleSpan; import android.text.style.StyleSpan;
import android.util.AttributeSet; import android.util.AttributeSet;
import android.util.Log;
import android.view.View; import android.view.View;
import android.widget.ImageView; import android.widget.ImageView;
import android.widget.RelativeLayout; import android.widget.RelativeLayout;
@ -39,7 +38,6 @@ import android.widget.TextView;
import org.thoughtcrime.securesms.database.model.ThreadRecord; import org.thoughtcrime.securesms.database.model.ThreadRecord;
import org.thoughtcrime.securesms.recipients.Recipient; import org.thoughtcrime.securesms.recipients.Recipient;
import org.thoughtcrime.securesms.recipients.Recipients; import org.thoughtcrime.securesms.recipients.Recipients;
import org.thoughtcrime.securesms.util.BitmapUtil;
import org.thoughtcrime.securesms.util.DateUtils; import org.thoughtcrime.securesms.util.DateUtils;
import org.thoughtcrime.securesms.util.Emoji; import org.thoughtcrime.securesms.util.Emoji;
@ -131,7 +129,8 @@ public class ConversationListItem extends RelativeLayout
private void setContactPhoto(final Recipient recipient) { private void setContactPhoto(final Recipient recipient) {
if (recipient == null) return; if (recipient == null) return;
contactPhotoImage.setImageBitmap(BitmapUtil.getCircleCroppedBitmap(recipient.getContactPhoto())); contactPhotoImage.setImageBitmap(recipient.getCircleCroppedContactPhoto());
if (!recipient.isGroupRecipient()) { if (!recipient.isGroupRecipient()) {
contactPhotoImage.setOnClickListener(new View.OnClickListener() { contactPhotoImage.setOnClickListener(new View.OnClickListener() {
@Override @Override

View File

@ -21,9 +21,13 @@ public class ContactPhotoFactory {
private static final Object defaultPhotoLock = new Object(); private static final Object defaultPhotoLock = new Object();
private static final Object defaultGroupPhotoLock = 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 defaultContactPhoto;
private static Bitmap defaultGroupContactPhoto; private static Bitmap defaultGroupContactPhoto;
private static Bitmap defaultContactPhotoCropped;
private static Bitmap defaultGroupContactPhotoCropped;
private static final Map<Uri,Bitmap> localUserContactPhotoCache = private static final Map<Uri,Bitmap> localUserContactPhotoCache =
Collections.synchronizedMap(new LRUCache<Uri,Bitmap>(2)); Collections.synchronizedMap(new LRUCache<Uri,Bitmap>(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) { public static Bitmap getLocalUserContactPhoto(Context context, Uri uri) {
if (uri == null) return getDefaultContactPhoto(context); if (uri == null) return getDefaultContactPhoto(context);

View File

@ -25,6 +25,7 @@ import android.util.Log;
import org.thoughtcrime.securesms.contacts.ContactPhotoFactory; import org.thoughtcrime.securesms.contacts.ContactPhotoFactory;
import org.thoughtcrime.securesms.recipients.RecipientProvider.RecipientDetails; import org.thoughtcrime.securesms.recipients.RecipientProvider.RecipientDetails;
import org.thoughtcrime.securesms.util.BitmapUtil;
import org.thoughtcrime.securesms.util.GroupUtil; import org.thoughtcrime.securesms.util.GroupUtil;
import org.whispersystems.textsecure.storage.CanonicalRecipient; import org.whispersystems.textsecure.storage.CanonicalRecipient;
import org.whispersystems.textsecure.util.FutureTaskListener; import org.whispersystems.textsecure.util.FutureTaskListener;
@ -52,13 +53,17 @@ public class Recipient implements Parcelable, CanonicalRecipient {
private final long recipientId; private final long recipientId;
private String name; private String name;
private Bitmap contactPhoto; private Bitmap contactPhoto;
private Bitmap circleCroppedContactPhoto;
private Uri contactUri; private Uri contactUri;
Recipient(String number, Bitmap contactPhoto, long recipientId, Recipient(String number, Bitmap contactPhoto, Bitmap circleCroppedContactPhoto,
ListenableFutureTask<RecipientDetails> future) long recipientId, ListenableFutureTask<RecipientDetails> future)
{ {
this.number = number; this.number = number;
this.circleCroppedContactPhoto = circleCroppedContactPhoto;
this.contactPhoto = contactPhoto; this.contactPhoto = contactPhoto;
this.recipientId = recipientId; this.recipientId = recipientId;
@ -72,7 +77,8 @@ public class Recipient implements Parcelable, CanonicalRecipient {
Recipient.this.name = result.name; Recipient.this.name = result.name;
Recipient.this.contactUri = result.contactUri; Recipient.this.contactUri = result.contactUri;
Recipient.this.contactPhoto = result.avatar; Recipient.this.contactPhoto = result.avatar;
localListeners = (HashSet<RecipientModifiedListener>)listeners.clone(); Recipient.this.circleCroppedContactPhoto = result.croppedAvatar;
localListeners = (HashSet<RecipientModifiedListener>) listeners.clone();
listeners.clear(); listeners.clear();
} }
@ -174,6 +180,10 @@ public class Recipient implements Parcelable, CanonicalRecipient {
return contactPhoto; return contactPhoto;
} }
public synchronized Bitmap getCircleCroppedContactPhoto() {
return this.circleCroppedContactPhoto;
}
public static Recipient getUnknownRecipient(Context context) { public static Recipient getUnknownRecipient(Context context) {
return new Recipient("Unknown", "Unknown", -1, null, ContactPhotoFactory.getDefaultContactPhoto(context)); return new Recipient("Unknown", "Unknown", -1, null, ContactPhotoFactory.getDefaultContactPhoto(context));
} }

View File

@ -21,7 +21,6 @@ import android.database.Cursor;
import android.graphics.Bitmap; import android.graphics.Bitmap;
import android.graphics.BitmapFactory; import android.graphics.BitmapFactory;
import android.net.Uri; import android.net.Uri;
import android.provider.ContactsContract;
import android.provider.ContactsContract.Contacts; import android.provider.ContactsContract.Contacts;
import android.provider.ContactsContract.PhoneLookup; import android.provider.ContactsContract.PhoneLookup;
import android.util.Log; 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.CanonicalAddressDatabase;
import org.thoughtcrime.securesms.database.DatabaseFactory; import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.database.GroupDatabase; import org.thoughtcrime.securesms.database.GroupDatabase;
import org.thoughtcrime.securesms.util.BitmapUtil;
import org.thoughtcrime.securesms.util.GroupUtil; import org.thoughtcrime.securesms.util.GroupUtil;
import org.thoughtcrime.securesms.util.LRUCache; import org.thoughtcrime.securesms.util.LRUCache;
import org.whispersystems.textsecure.util.ListenableFutureTask;
import org.thoughtcrime.securesms.util.Util; import org.thoughtcrime.securesms.util.Util;
import org.whispersystems.textsecure.util.ListenableFutureTask;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream;
import java.util.Collections; import java.util.Collections;
import java.util.Map; import java.util.Map;
import java.util.concurrent.Callable; import java.util.concurrent.Callable;
@ -103,10 +102,18 @@ public class RecipientProvider {
asyncRecipientResolver.submit(future); asyncRecipientResolver.submit(future);
final Bitmap defaultPhoto = isGroupRecipient Bitmap contactPhoto;
? ContactPhotoFactory.getDefaultGroupPhoto(context) Bitmap contactPhotoCropped;
: ContactPhotoFactory.getDefaultContactPhoto(context);
Recipient recipient = new Recipient(number, defaultPhoto, recipientId, future); 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); recipientCache.put(recipientId, recipient);
return recipient; return recipient;
@ -132,7 +139,8 @@ public class RecipientProvider {
Bitmap contactPhoto = ContactPhotoFactory.getContactPhoto(context, Uri.withAppendedPath(Contacts.CONTENT_URI, Bitmap contactPhoto = ContactPhotoFactory.getContactPhoto(context, Uri.withAppendedPath(Contacts.CONTENT_URI,
cursor.getLong(2)+"")); cursor.getLong(2)+""));
return new RecipientDetails(cursor.getString(0), contactUri, contactPhoto); return new RecipientDetails(cursor.getString(0), contactUri, contactPhoto,
BitmapUtil.getCircleCroppedBitmap(contactPhoto));
} }
} finally { } finally {
if (cursor != null) if (cursor != null)
@ -154,7 +162,7 @@ public class RecipientProvider {
if (avatarBytes == null) avatar = ContactPhotoFactory.getDefaultGroupPhoto(context); if (avatarBytes == null) avatar = ContactPhotoFactory.getDefaultGroupPhoto(context);
else avatar = BitmapFactory.decodeByteArray(avatarBytes, 0, avatarBytes.length); 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; return null;
@ -167,11 +175,13 @@ public class RecipientProvider {
public static class RecipientDetails { public static class RecipientDetails {
public final String name; public final String name;
public final Bitmap avatar; public final Bitmap avatar;
public final Bitmap croppedAvatar;
public final Uri contactUri; public final Uri contactUri;
public RecipientDetails(String name, Uri contactUri, Bitmap avatar) { public RecipientDetails(String name, Uri contactUri, Bitmap avatar, Bitmap croppedAvatar) {
this.name = name; this.name = name;
this.avatar = avatar; this.avatar = avatar;
this.croppedAvatar = croppedAvatar;
this.contactUri = contactUri; this.contactUri = contactUri;
} }
} }