From 0485da8488c2e1a671bac3e80b990b9003c1cb91 Mon Sep 17 00:00:00 2001 From: iNPUTmice Date: Sun, 15 Feb 2015 18:48:05 +0100 Subject: [PATCH] loading avatars in seperate tasks --- .../conversations/services/AvatarService.java | 40 +++++--- .../ui/adapter/ConversationAdapter.java | 90 +++++++++++++++++- .../ui/adapter/ListItemAdapter.java | 91 ++++++++++++++++++- 3 files changed, 203 insertions(+), 18 deletions(-) diff --git a/src/main/java/eu/siacs/conversations/services/AvatarService.java b/src/main/java/eu/siacs/conversations/services/AvatarService.java index f28dc24e5..7412eb933 100644 --- a/src/main/java/eu/siacs/conversations/services/AvatarService.java +++ b/src/main/java/eu/siacs/conversations/services/AvatarService.java @@ -38,10 +38,10 @@ public class AvatarService { this.mXmppConnectionService = service; } - public Bitmap get(final Contact contact, final int size) { + private Bitmap get(final Contact contact, final int size, boolean cachedOnly) { final String KEY = key(contact, size); Bitmap avatar = this.mXmppConnectionService.getBitmapCache().get(KEY); - if (avatar != null) { + if (avatar != null || cachedOnly) { return avatar; } if (contact.getProfilePhoto() != null) { @@ -51,7 +51,7 @@ public class AvatarService { avatar = mXmppConnectionService.getFileBackend().getAvatar(contact.getAvatar(), size); } if (avatar == null) { - avatar = get(contact.getDisplayName(), size); + avatar = get(contact.getDisplayName(), size, cachedOnly); } this.mXmppConnectionService.getBitmapCache().put(KEY, avatar); return avatar; @@ -77,25 +77,33 @@ public class AvatarService { } public Bitmap get(ListItem item, int size) { + return get(item,size,false); + } + + public Bitmap get(ListItem item, int size, boolean cachedOnly) { if (item instanceof Contact) { - return get((Contact) item, size); + return get((Contact) item, size,cachedOnly); } else if (item instanceof Bookmark) { Bookmark bookmark = (Bookmark) item; if (bookmark.getConversation() != null) { - return get(bookmark.getConversation(), size); + return get(bookmark.getConversation(), size, cachedOnly); } else { - return get(bookmark.getDisplayName(), size); + return get(bookmark.getDisplayName(), size, cachedOnly); } } else { - return get(item.getDisplayName(), size); + return get(item.getDisplayName(), size, cachedOnly); } } public Bitmap get(Conversation conversation, int size) { + return get(conversation,size,false); + } + + public Bitmap get(Conversation conversation, int size, boolean cachedOnly) { if (conversation.getMode() == Conversation.MODE_SINGLE) { - return get(conversation.getContact(), size); + return get(conversation.getContact(), size, cachedOnly); } else { - return get(conversation.getMucOptions(), size); + return get(conversation.getMucOptions(), size, cachedOnly); } } @@ -107,10 +115,10 @@ public class AvatarService { } } - public Bitmap get(MucOptions mucOptions, int size) { + private Bitmap get(MucOptions mucOptions, int size, boolean cachedOnly) { final String KEY = key(mucOptions, size); Bitmap bitmap = this.mXmppConnectionService.getBitmapCache().get(KEY); - if (bitmap != null) { + if (bitmap != null || cachedOnly) { return bitmap; } final List users = new ArrayList<>(mucOptions.getUsers()); @@ -179,7 +187,7 @@ public class AvatarService { avatar = mXmppConnectionService.getFileBackend().getAvatar( account.getAvatar(), size); if (avatar == null) { - avatar = get(account.getJid().toBareJid().toString(), size); + avatar = get(account.getJid().toBareJid().toString(), size,false); } mXmppConnectionService.getBitmapCache().put(KEY, avatar); return avatar; @@ -204,10 +212,14 @@ public class AvatarService { + String.valueOf(size); } - public Bitmap get(final String name, final int size) { + public Bitmap get(String name, int size) { + return get(name,size,false); + } + + public Bitmap get(final String name, final int size, boolean cachedOnly) { final String KEY = key(name, size); Bitmap bitmap = mXmppConnectionService.getBitmapCache().get(KEY); - if (bitmap != null) { + if (bitmap != null || cachedOnly) { return bitmap; } bitmap = Bitmap.createBitmap(size, size, Bitmap.Config.ARGB_8888); diff --git a/src/main/java/eu/siacs/conversations/ui/adapter/ConversationAdapter.java b/src/main/java/eu/siacs/conversations/ui/adapter/ConversationAdapter.java index 38c321d07..02a3dfef0 100644 --- a/src/main/java/eu/siacs/conversations/ui/adapter/ConversationAdapter.java +++ b/src/main/java/eu/siacs/conversations/ui/adapter/ConversationAdapter.java @@ -1,8 +1,13 @@ package eu.siacs.conversations.ui.adapter; import android.content.Context; +import android.content.res.Resources; +import android.graphics.Bitmap; import android.graphics.Color; import android.graphics.Typeface; +import android.graphics.drawable.BitmapDrawable; +import android.graphics.drawable.Drawable; +import android.os.AsyncTask; import android.util.Pair; import android.view.LayoutInflater; import android.view.View; @@ -11,12 +16,13 @@ import android.widget.ArrayAdapter; import android.widget.ImageView; import android.widget.TextView; +import java.lang.ref.WeakReference; import java.util.List; +import java.util.concurrent.RejectedExecutionException; import eu.siacs.conversations.R; import eu.siacs.conversations.entities.Conversation; import eu.siacs.conversations.entities.Downloadable; -import eu.siacs.conversations.entities.DownloadableFile; import eu.siacs.conversations.entities.Message; import eu.siacs.conversations.ui.ConversationActivity; import eu.siacs.conversations.ui.XmppActivity; @@ -98,8 +104,88 @@ public class ConversationAdapter extends ArrayAdapter { mTimestamp.setText(UIHelper.readableTimeDifference(activity,conversation.getLatestMessage().getTimeSent())); ImageView profilePicture = (ImageView) view.findViewById(R.id.conversation_image); - profilePicture.setImageBitmap(activity.avatarService().get(conversation, activity.getPixel(56))); + loadAvatar(conversation,profilePicture); return view; } + + class BitmapWorkerTask extends AsyncTask { + private final WeakReference imageViewReference; + private Conversation conversation = null; + + public BitmapWorkerTask(ImageView imageView) { + imageViewReference = new WeakReference<>(imageView); + } + + @Override + protected Bitmap doInBackground(Conversation... params) { + return activity.avatarService().get(params[0], activity.getPixel(56)); + } + + @Override + protected void onPostExecute(Bitmap bitmap) { + if (bitmap != null) { + final ImageView imageView = imageViewReference.get(); + if (imageView != null) { + imageView.setImageBitmap(bitmap); + imageView.setBackgroundColor(0x00000000); + } + } + } + } + + public void loadAvatar(Conversation conversation, ImageView imageView) { + Bitmap bm = activity.avatarService().get(conversation,activity.getPixel(56),true); + if (bm != null) { + imageView.setImageBitmap(bm); + imageView.setBackgroundColor(0x00000000); + } else if (cancelPotentialWork(conversation, imageView)) { + imageView.setBackgroundColor(0xff333333); + final BitmapWorkerTask task = new BitmapWorkerTask(imageView); + final AsyncDrawable asyncDrawable = new AsyncDrawable(activity.getResources(), null, task); + imageView.setImageDrawable(asyncDrawable); + try { + task.execute(conversation); + } catch (final RejectedExecutionException ignored) { + } + } + } + + public static boolean cancelPotentialWork(Conversation conversation, ImageView imageView) { + final BitmapWorkerTask bitmapWorkerTask = getBitmapWorkerTask(imageView); + + if (bitmapWorkerTask != null) { + final Conversation oldConversation = bitmapWorkerTask.conversation; + if (oldConversation == null || conversation != oldConversation) { + bitmapWorkerTask.cancel(true); + } else { + return false; + } + } + return true; + } + + private static BitmapWorkerTask getBitmapWorkerTask(ImageView imageView) { + if (imageView != null) { + final Drawable drawable = imageView.getDrawable(); + if (drawable instanceof AsyncDrawable) { + final AsyncDrawable asyncDrawable = (AsyncDrawable) drawable; + return asyncDrawable.getBitmapWorkerTask(); + } + } + return null; + } + + static class AsyncDrawable extends BitmapDrawable { + private final WeakReference bitmapWorkerTaskReference; + + public AsyncDrawable(Resources res, Bitmap bitmap, BitmapWorkerTask bitmapWorkerTask) { + super(res, bitmap); + bitmapWorkerTaskReference = new WeakReference<>(bitmapWorkerTask); + } + + public BitmapWorkerTask getBitmapWorkerTask() { + return bitmapWorkerTaskReference.get(); + } + } } \ No newline at end of file diff --git a/src/main/java/eu/siacs/conversations/ui/adapter/ListItemAdapter.java b/src/main/java/eu/siacs/conversations/ui/adapter/ListItemAdapter.java index 91fb021cc..37865aca0 100644 --- a/src/main/java/eu/siacs/conversations/ui/adapter/ListItemAdapter.java +++ b/src/main/java/eu/siacs/conversations/ui/adapter/ListItemAdapter.java @@ -1,15 +1,23 @@ package eu.siacs.conversations.ui.adapter; +import java.lang.ref.WeakReference; import java.util.List; +import java.util.concurrent.RejectedExecutionException; import eu.siacs.conversations.Config; import eu.siacs.conversations.R; +import eu.siacs.conversations.entities.Conversation; import eu.siacs.conversations.entities.ListItem; import eu.siacs.conversations.ui.XmppActivity; import eu.siacs.conversations.xmpp.jid.Jid; import android.content.Context; import android.content.SharedPreferences; +import android.content.res.Resources; +import android.graphics.Bitmap; +import android.graphics.drawable.BitmapDrawable; +import android.graphics.drawable.Drawable; +import android.os.AsyncTask; import android.preference.PreferenceManager; import android.util.Log; import android.view.LayoutInflater; @@ -77,8 +85,7 @@ public class ListItemAdapter extends ArrayAdapter { tvJid.setText(""); } tvName.setText(item.getDisplayName()); - picture.setImageBitmap(activity.avatarService().get(item, - activity.getPixel(48))); + loadAvatar(item,picture); return view; } @@ -90,4 +97,84 @@ public class ListItemAdapter extends ArrayAdapter { public void onTagClicked(String tag); } + class BitmapWorkerTask extends AsyncTask { + private final WeakReference imageViewReference; + private ListItem item = null; + + public BitmapWorkerTask(ImageView imageView) { + imageViewReference = new WeakReference<>(imageView); + } + + @Override + protected Bitmap doInBackground(ListItem... params) { + return activity.avatarService().get(params[0], activity.getPixel(48)); + } + + @Override + protected void onPostExecute(Bitmap bitmap) { + if (bitmap != null) { + final ImageView imageView = imageViewReference.get(); + if (imageView != null) { + imageView.setImageBitmap(bitmap); + imageView.setBackgroundColor(0x00000000); + } + } + } + } + + public void loadAvatar(ListItem item, ImageView imageView) { + Bitmap bm = activity.avatarService().get(item,activity.getPixel(56),true); + if (bm != null) { + imageView.setImageBitmap(bm); + imageView.setBackgroundColor(0x00000000); + } else if (cancelPotentialWork(item, imageView)) { + imageView.setBackgroundColor(0xff333333); + final BitmapWorkerTask task = new BitmapWorkerTask(imageView); + final AsyncDrawable asyncDrawable = new AsyncDrawable(activity.getResources(), null, task); + imageView.setImageDrawable(asyncDrawable); + try { + task.execute(item); + } catch (final RejectedExecutionException ignored) { + } + } + } + + public static boolean cancelPotentialWork(ListItem item, ImageView imageView) { + final BitmapWorkerTask bitmapWorkerTask = getBitmapWorkerTask(imageView); + + if (bitmapWorkerTask != null) { + final ListItem oldItem = bitmapWorkerTask.item; + if (oldItem == null || item != oldItem) { + bitmapWorkerTask.cancel(true); + } else { + return false; + } + } + return true; + } + + private static BitmapWorkerTask getBitmapWorkerTask(ImageView imageView) { + if (imageView != null) { + final Drawable drawable = imageView.getDrawable(); + if (drawable instanceof AsyncDrawable) { + final AsyncDrawable asyncDrawable = (AsyncDrawable) drawable; + return asyncDrawable.getBitmapWorkerTask(); + } + } + return null; + } + + static class AsyncDrawable extends BitmapDrawable { + private final WeakReference bitmapWorkerTaskReference; + + public AsyncDrawable(Resources res, Bitmap bitmap, BitmapWorkerTask bitmapWorkerTask) { + super(res, bitmap); + bitmapWorkerTaskReference = new WeakReference<>(bitmapWorkerTask); + } + + public BitmapWorkerTask getBitmapWorkerTask() { + return bitmapWorkerTaskReference.get(); + } + } + }