am 35e82d4f: Move getAvatarIcon off UI
* commit '35e82d4f9522906f7953667cf5c5f8137ec2f5ac':
Move getAvatarIcon off UI
diff --git a/src/com/android/ex/chips/BaseRecipientAdapter.java b/src/com/android/ex/chips/BaseRecipientAdapter.java
index 6b37359..f38213a 100644
--- a/src/com/android/ex/chips/BaseRecipientAdapter.java
+++ b/src/com/android/ex/chips/BaseRecipientAdapter.java
@@ -840,8 +840,8 @@
return mTempEntries != null ? mTempEntries : mEntries;
}
- protected void fetchPhoto(final RecipientEntry entry, final Uri photoThumbnailUri) {
- mPhotoManager.populatePhotoBytesSync(entry);
+ protected void fetchPhoto(final RecipientEntry entry, PhotoManager.PhotoManagerCallback cb) {
+ mPhotoManager.populatePhotoBytesAsync(entry, cb);
}
private Cursor doQuery(CharSequence constraint, int limit, Long directoryId) {
diff --git a/src/com/android/ex/chips/DefaultPhotoManager.java b/src/com/android/ex/chips/DefaultPhotoManager.java
index 04b772e..265c410 100644
--- a/src/com/android/ex/chips/DefaultPhotoManager.java
+++ b/src/com/android/ex/chips/DefaultPhotoManager.java
@@ -139,64 +139,4 @@
};
photoLoadTask.executeOnExecutor(AsyncTask.SERIAL_EXECUTOR);
}
-
- @Override
- public void populatePhotoBytesSync(RecipientEntry entry) {
- final Uri photoThumbnailUri = entry.getPhotoThumbnailUri();
- if (photoThumbnailUri == null) {
- return;
- }
-
- byte[] photoBytes = mPhotoCacheMap.get(photoThumbnailUri);
- if (photoBytes != null) {
- entry.setPhotoBytes(photoBytes);
- return;
- }
- final Cursor photoCursor = mContentResolver.query(
- photoThumbnailUri, PhotoQuery.PROJECTION, null, null, null);
- if (photoCursor != null) {
- try {
- if (photoCursor.moveToFirst()) {
- photoBytes = photoCursor.getBlob(PhotoQuery.PHOTO);
- entry.setPhotoBytes(photoBytes);
- mPhotoCacheMap.put(photoThumbnailUri, photoBytes);
- }
- } finally {
- photoCursor.close();
- }
- } else {
- InputStream inputStream = null;
- ByteArrayOutputStream outputStream = null;
- try {
- inputStream = mContentResolver.openInputStream(photoThumbnailUri);
- final Bitmap bitmap = BitmapFactory.decodeStream(inputStream);
-
- if (bitmap != null) {
- outputStream = new ByteArrayOutputStream();
- bitmap.compress(Bitmap.CompressFormat.PNG, 100, outputStream);
- photoBytes = outputStream.toByteArray();
-
- entry.setPhotoBytes(photoBytes);
- mPhotoCacheMap.put(photoThumbnailUri, photoBytes);
- }
- } catch (final FileNotFoundException e) {
- Log.w(TAG, "Error opening InputStream for photo", e);
- } finally {
- try {
- if (inputStream != null) {
- inputStream.close();
- }
- } catch (IOException e) {
- Log.e(TAG, "Error closing photo input stream", e);
- }
- try {
- if (outputStream != null) {
- outputStream.close();
- }
- } catch (IOException e) {
- Log.e(TAG, "Error closing photo output stream", e);
- }
- }
- }
- }
}
diff --git a/src/com/android/ex/chips/PhotoManager.java b/src/com/android/ex/chips/PhotoManager.java
index 8cb8df6..51a5f79 100644
--- a/src/com/android/ex/chips/PhotoManager.java
+++ b/src/com/android/ex/chips/PhotoManager.java
@@ -37,12 +37,6 @@
*/
void populatePhotoBytesAsync(RecipientEntry entry, PhotoManagerCallback callback);
- /**
- * Sets the {@link com.android.ex.chips.RecipientEntry}'s photo bytes. All work
- * is performed synchronously.
- */
- void populatePhotoBytesSync(RecipientEntry entry);
-
interface PhotoManagerCallback {
void onPhotoBytesAsynchronouslyPopulated();
}
diff --git a/src/com/android/ex/chips/RecipientEditTextView.java b/src/com/android/ex/chips/RecipientEditTextView.java
index 15388a7..7682691 100644
--- a/src/com/android/ex/chips/RecipientEditTextView.java
+++ b/src/com/android/ex/chips/RecipientEditTextView.java
@@ -620,14 +620,19 @@
*/
private Bitmap createSelectedChip(RecipientEntry contact, TextPaint paint) {
paint.setColor(sSelectedTextColor);
- Bitmap photo;
- if (mDisableDelete) {
- // Show the avatar instead if we don't want to delete
- photo = getAvatarIcon(contact);
- } else {
- photo = ((BitmapDrawable) mChipDelete).getBitmap();
+ final ChipBitmapContainer bitmapContainer = createChipBitmap(contact, paint,
+ mChipBackgroundPressed);
+
+ if (bitmapContainer.loadIcon) {
+ if (mDisableDelete) {
+ // Show the avatar instead if we don't want to delete
+ loadAvatarIcon(contact, bitmapContainer, paint);
+ } else {
+ drawIcon(bitmapContainer, ((BitmapDrawable) mChipDelete).getBitmap(), paint);
+ }
}
- return createChipBitmap(contact, paint, photo, mChipBackgroundPressed);
+
+ return bitmapContainer.bitmap;
}
/**
@@ -638,17 +643,25 @@
*/
private Bitmap createUnselectedChip(RecipientEntry contact, TextPaint paint) {
Drawable background = getChipBackground(contact);
- Bitmap photo = getAvatarIcon(contact);
paint.setColor(getContext().getResources().getColor(android.R.color.black));
- return createChipBitmap(contact, paint, photo, background);
+ ChipBitmapContainer bitmapContainer = createChipBitmap(contact, paint, background);
+
+ if (bitmapContainer.loadIcon) {
+ loadAvatarIcon(contact, bitmapContainer, paint);
+ }
+ return bitmapContainer.bitmap;
}
- private Bitmap createChipBitmap(RecipientEntry contact, TextPaint paint, Bitmap icon,
- Drawable background) {
+ private ChipBitmapContainer createChipBitmap(RecipientEntry contact, TextPaint paint,
+ Drawable background) {
+ final ChipBitmapContainer result = new ChipBitmapContainer();
+
if (background == null) {
- Log.w(TAG, "Unable to draw a background for the chips as it was never set");
- return Bitmap.createBitmap(
+ Log.w(TAG, "Unable to draw a background for the chip as it was never set");
+ result.bitmap = Bitmap.createBitmap(
(int) mChipHeight * 2, (int) mChipHeight, Bitmap.Config.ARGB_8888);
+ result.loadIcon = false;
+ return result;
}
Rect backgroundPadding = new Rect();
@@ -674,8 +687,8 @@
+ backgroundPadding.left + backgroundPadding.right);
// Create the background of the chip.
- Bitmap tmpBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
- Canvas canvas = new Canvas(tmpBitmap);
+ result.bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
+ final Canvas canvas = new Canvas(result.bitmap);
// Draw the background drawable
background.setBounds(0, 0, width, height);
@@ -686,19 +699,27 @@
width - backgroundPadding.right - mChipPadding - textWidth;
canvas.drawText(ellipsizedText, 0, ellipsizedText.length(),
textX, getTextYOffset(ellipsizedText.toString(), paint, height), paint);
- if (icon != null) {
- // Draw the icon
- int iconX = shouldPositionAvatarOnRight() ?
- width - backgroundPadding.right - iconWidth :
- backgroundPadding.left;
- RectF src = new RectF(0, 0, icon.getWidth(), icon.getHeight());
- RectF dst = new RectF(iconX,
- 0 + backgroundPadding.top,
- iconX + iconWidth,
- height - backgroundPadding.bottom);
- drawIconOnCanvas(icon, canvas, paint, src, dst);
- }
- return tmpBitmap;
+
+ // Set the variables that are needed to draw the icon bitmap once it's loaded
+ int iconX = shouldPositionAvatarOnRight() ? width - backgroundPadding.right - iconWidth :
+ backgroundPadding.left;
+ result.left = iconX;
+ result.top = backgroundPadding.top;
+ result.right = iconX + iconWidth;
+ result.bottom = height - backgroundPadding.bottom;
+
+ return result;
+ }
+
+ /**
+ * Helper function that draws the loaded icon bitmap into the chips bitmap
+ */
+ private void drawIcon(ChipBitmapContainer bitMapResult, Bitmap icon, Paint paint) {
+ final Canvas canvas = new Canvas(bitMapResult.bitmap);
+ final RectF src = new RectF(0, 0, icon.getWidth(), icon.getHeight());
+ final RectF dst = new RectF(bitMapResult.left, bitMapResult.top, bitMapResult.right,
+ bitMapResult.bottom);
+ drawIconOnCanvas(icon, canvas, paint, src, dst);
}
/**
@@ -718,7 +739,8 @@
* Returns the avatar icon to use for this recipient entry. Returns null if we don't want to
* draw an icon for this recipient.
*/
- private Bitmap getAvatarIcon(RecipientEntry contact) {
+ private void loadAvatarIcon(final RecipientEntry contact,
+ final ChipBitmapContainer bitmapContainer, final Paint paint) {
// Don't draw photos for recipients that have been typed in OR generated on the fly.
long contactId = contact.getContactId();
boolean drawPhotos = isPhoneQuery() ?
@@ -728,24 +750,34 @@
!TextUtils.isEmpty(contact.getDisplayName())));
if (drawPhotos) {
- byte[] photoBytes = contact.getPhotoBytes();
+ final byte[] origPhotoBytes = contact.getPhotoBytes();
// There may not be a photo yet if anything but the first contact address
// was selected.
- if (photoBytes == null && (contact.getPhotoThumbnailUri() != null ||
+ if (origPhotoBytes == null && (contact.getPhotoThumbnailUri() != null ||
getAdapter().ignoreNullThumbnailUri())) {
// TODO: cache this in the recipient entry?
- getAdapter().fetchPhoto(contact, contact.getPhotoThumbnailUri());
- photoBytes = contact.getPhotoBytes();
- }
- if (photoBytes != null) {
- return BitmapFactory.decodeByteArray(photoBytes, 0, photoBytes.length);
+ getAdapter().fetchPhoto(contact, new PhotoManager.PhotoManagerCallback() {
+ @Override
+ public void onPhotoBytesAsynchronouslyPopulated() {
+ final byte[] loadedPhotoBytes = contact.getPhotoBytes();
+ final Bitmap icon;
+ if (loadedPhotoBytes != null) {
+ icon = BitmapFactory.decodeByteArray(loadedPhotoBytes, 0,
+ loadedPhotoBytes.length);
+ } else {
+ // TODO: can the scaled down default photo be cached?
+ icon = mDefaultContactPhoto;
+ }
+ // This is called on the main thread so we can draw the icon here
+ drawIcon(bitmapContainer, icon, paint);
+ }
+ });
} else {
- // TODO: can the scaled down default photo be cached?
- return mDefaultContactPhoto;
+ final Bitmap icon = BitmapFactory.decodeByteArray(origPhotoBytes, 0,
+ origPhotoBytes.length);
+ drawIcon(bitmapContainer, icon, paint);
}
}
-
- return null;
}
/**
@@ -3006,4 +3038,14 @@
editable.insert(chipInsertionPoint, chip);
}
}
+
+ private static class ChipBitmapContainer {
+ Bitmap bitmap;
+ // information used for positioning the loaded icon
+ boolean loadIcon = true;
+ float left;
+ float top;
+ float right;
+ float bottom;
+ }
}