AvatarWorkerTask.java

  1package eu.siacs.conversations.ui.util;
  2
  3import android.content.Context;
  4import android.content.res.Resources;
  5import android.graphics.Bitmap;
  6import android.graphics.drawable.BitmapDrawable;
  7import android.graphics.drawable.Drawable;
  8import android.os.AsyncTask;
  9import android.widget.ImageView;
 10
 11import androidx.annotation.DimenRes;
 12
 13import java.lang.ref.WeakReference;
 14import java.util.concurrent.RejectedExecutionException;
 15
 16import eu.siacs.conversations.R;
 17import eu.siacs.conversations.entities.Account;
 18import eu.siacs.conversations.services.AvatarService;
 19import eu.siacs.conversations.ui.XmppActivity;
 20
 21public class AvatarWorkerTask extends AsyncTask<AvatarService.Avatarable, Void, Bitmap> {
 22    private final WeakReference<ImageView> imageViewReference;
 23    private AvatarService.Avatarable avatarable = null;
 24    private @DimenRes
 25    final int size;
 26
 27    public AvatarWorkerTask(ImageView imageView, @DimenRes int size) {
 28        imageViewReference = new WeakReference<>(imageView);
 29        this.size = size;
 30    }
 31
 32    @Override
 33    protected Bitmap doInBackground(AvatarService.Avatarable... params) {
 34        this.avatarable = params[0];
 35        final XmppActivity activity = XmppActivity.find(imageViewReference);
 36        if (activity == null) {
 37            return null;
 38        }
 39        return activity.avatarService().get(avatarable, (int) activity.getResources().getDimension(size), isCancelled());
 40    }
 41
 42    @Override
 43    protected void onPostExecute(Bitmap bitmap) {
 44        if (bitmap != null && !isCancelled()) {
 45            final ImageView imageView = imageViewReference.get();
 46            if (imageView != null) {
 47                imageView.setImageBitmap(bitmap);
 48                imageView.setBackgroundColor(0x00000000);
 49            }
 50        }
 51    }
 52
 53    public static boolean cancelPotentialWork(AvatarService.Avatarable avatarable, ImageView imageView) {
 54        final AvatarWorkerTask workerTask = getBitmapWorkerTask(imageView);
 55
 56        if (workerTask != null) {
 57            final AvatarService.Avatarable old= workerTask.avatarable;
 58            if (old == null || avatarable != old) {
 59                workerTask.cancel(true);
 60            } else {
 61                return false;
 62            }
 63        }
 64        return true;
 65    }
 66
 67    public static AvatarWorkerTask getBitmapWorkerTask(ImageView imageView) {
 68        if (imageView != null) {
 69            final Drawable drawable = imageView.getDrawable();
 70            if (drawable instanceof AsyncDrawable) {
 71                final AsyncDrawable asyncDrawable = (AsyncDrawable) drawable;
 72                return asyncDrawable.getAvatarWorkerTask();
 73            }
 74        }
 75        return null;
 76    }
 77
 78    public static void loadAvatar(final AvatarService.Avatarable avatarable, final ImageView imageView, final @DimenRes int size) {
 79        if (cancelPotentialWork(avatarable, imageView)) {
 80            final XmppActivity activity = XmppActivity.find(imageView);
 81            if (activity == null) {
 82                return;
 83            }
 84            final Bitmap bm = activity.avatarService().get(avatarable, (int) activity.getResources().getDimension(size), true);
 85            setContentDescription(avatarable, imageView);
 86            if (bm != null) {
 87                cancelPotentialWork(avatarable, imageView);
 88                imageView.setImageBitmap(bm);
 89                imageView.setBackgroundColor(0x00000000);
 90            } else {
 91                imageView.setBackgroundColor(avatarable.getAvatarBackgroundColor());
 92                imageView.setImageDrawable(null);
 93                final AvatarWorkerTask task = new AvatarWorkerTask(imageView, size);
 94                final AsyncDrawable asyncDrawable = new AsyncDrawable(activity.getResources(), null, task);
 95                imageView.setImageDrawable(asyncDrawable);
 96                try {
 97                    task.execute(avatarable);
 98                } catch (final RejectedExecutionException ignored) {
 99                }
100            }
101        }
102    }
103
104    private static void setContentDescription(final AvatarService.Avatarable avatarable, final ImageView imageView) {
105        final Context context = imageView.getContext();
106        if (avatarable instanceof Account) {
107            imageView.setContentDescription(context.getString(R.string.your_avatar));
108        } else {
109            imageView.setContentDescription(context.getString(R.string.avatar_for_x, avatarable.getAvatarName()));
110        }
111    }
112
113    static class AsyncDrawable extends BitmapDrawable {
114        private final WeakReference<AvatarWorkerTask> avatarWorkerTaskReference;
115
116        AsyncDrawable(Resources res, Bitmap bitmap, AvatarWorkerTask workerTask) {
117            super(res, bitmap);
118            avatarWorkerTaskReference = new WeakReference<>(workerTask);
119        }
120
121        AvatarWorkerTask getAvatarWorkerTask() {
122            return avatarWorkerTaskReference.get();
123        }
124    }
125}