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