Loading app/ui/src/main/java/com/fsck/k9/activity/misc/ContactPicture.java +1 −1 Original line number Diff line number Diff line Loading @@ -12,6 +12,6 @@ public class ContactPicture { public static ContactPictureLoader getContactPictureLoader(Context context) { ContactLetterBitmapCreator contactLetterBitmapCreator = DI.get(ContactLetterBitmapCreator.class); return new ContactPictureLoader(context, contactLetterBitmapCreator); return new ContactPictureLoader(context.getApplicationContext(), contactLetterBitmapCreator); } } app/ui/src/main/java/com/fsck/k9/contacts/ContactPictureLoader.kt +130 −170 Original line number Diff line number Diff line package com.fsck.k9.contacts; import java.io.IOException; import java.util.Locale; import android.content.Context; import android.content.res.Resources; import android.graphics.Bitmap; import android.graphics.Bitmap.CompressFormat; import android.net.Uri; import android.support.annotation.Nullable; import android.support.annotation.WorkerThread; import android.widget.ImageView; import com.bumptech.glide.Glide; import com.bumptech.glide.Priority; import com.bumptech.glide.load.ResourceDecoder; import com.bumptech.glide.load.data.DataFetcher; import com.bumptech.glide.load.engine.DiskCacheStrategy; import com.bumptech.glide.load.engine.Resource; import com.bumptech.glide.load.engine.bitmap_recycle.BitmapPool; import com.bumptech.glide.load.model.ModelLoader; import com.bumptech.glide.load.resource.bitmap.BitmapEncoder; import com.bumptech.glide.load.resource.bitmap.BitmapResource; import com.bumptech.glide.load.resource.bitmap.StreamBitmapDecoder; import com.bumptech.glide.load.resource.drawable.GlideDrawable; import com.bumptech.glide.load.resource.file.FileToStreamDecoder; import com.bumptech.glide.load.resource.transcode.BitmapToGlideDrawableTranscoder; import com.bumptech.glide.request.FutureTarget; import com.bumptech.glide.request.RequestListener; import com.bumptech.glide.request.target.Target; import com.fsck.k9.helper.Contacts; import com.fsck.k9.mail.Address; import com.fsck.k9.view.RecipientSelectView.Recipient; public class ContactPictureLoader { /** * Resize the pictures to the following value (device-independent pixels). */ private static final int PICTURE_SIZE = 40; private final Context context; private final ContactLetterBitmapCreator contactLetterBitmapCreator; private Contacts mContactsHelper; private int mPictureSizeInPx; public ContactPictureLoader(Context context, ContactLetterBitmapCreator contactLetterBitmapCreator) { this.context = context.getApplicationContext(); this.contactLetterBitmapCreator = contactLetterBitmapCreator; mContactsHelper = Contacts.getInstance(this.context); Resources resources = context.getResources(); float scale = resources.getDisplayMetrics().density; mPictureSizeInPx = (int) (PICTURE_SIZE * scale); } public void loadContactPicture(final Address address, final ImageView imageView) { Uri photoUri = mContactsHelper.getPhotoUri(address.getAddress()); loadContactPicture(photoUri, address, imageView); } public void loadContactPicture(Recipient recipient, ImageView imageView) { loadContactPicture(recipient.photoThumbnailUri, recipient.address, imageView); } private void loadFallbackPicture(Address address, ImageView imageView) { Context context = imageView.getContext(); package com.fsck.k9.contacts import android.content.Context import android.graphics.Bitmap import android.graphics.Bitmap.CompressFormat import android.net.Uri import android.support.annotation.WorkerThread import android.widget.ImageView import com.bumptech.glide.Glide import com.bumptech.glide.Priority import com.bumptech.glide.load.ResourceDecoder import com.bumptech.glide.load.data.DataFetcher import com.bumptech.glide.load.engine.DiskCacheStrategy import com.bumptech.glide.load.engine.Resource import com.bumptech.glide.load.model.ModelLoader import com.bumptech.glide.load.resource.bitmap.BitmapEncoder import com.bumptech.glide.load.resource.bitmap.BitmapResource import com.bumptech.glide.load.resource.bitmap.StreamBitmapDecoder import com.bumptech.glide.load.resource.drawable.GlideDrawable import com.bumptech.glide.load.resource.file.FileToStreamDecoder import com.bumptech.glide.load.resource.transcode.BitmapToGlideDrawableTranscoder import com.bumptech.glide.request.FutureTarget import com.bumptech.glide.request.RequestListener import com.bumptech.glide.request.target.Target import com.fsck.k9.helper.Contacts import com.fsck.k9.mail.Address import com.fsck.k9.view.RecipientSelectView.Recipient import java.util.Locale class ContactPictureLoader( private val context: Context, private val contactLetterBitmapCreator: ContactLetterBitmapCreator ) { private val contactsHelper: Contacts = Contacts.getInstance(context) private val pictureSizeInPx: Int = PICTURE_SIZE.toDip(context) fun loadContactPicture(address: Address, imageView: ImageView) { val photoUri = contactsHelper.getPhotoUri(address.address) loadContactPicture(photoUri, address, imageView) } fun loadContactPicture(recipient: Recipient, imageView: ImageView) { loadContactPicture(recipient.photoThumbnailUri, recipient.address, imageView) } private fun loadFallbackPicture(address: Address, imageView: ImageView) { val context = imageView.context Glide.with(context) .using(new FallbackGlideModelLoader(), FallbackGlideParams.class) .from(FallbackGlideParams.class) .as(Bitmap.class) .transcode(new BitmapToGlideDrawableTranscoder(context), GlideDrawable.class) .decoder(new FallbackGlideBitmapDecoder(context)) .encoder(new BitmapEncoder(Bitmap.CompressFormat.PNG, 0)) .cacheDecoder(new FileToStreamDecoder<>(new StreamBitmapDecoder(context))) .using(FallbackGlideModelLoader(), FallbackGlideParams::class.java) .from(FallbackGlideParams::class.java) .`as`(Bitmap::class.java) .transcode(BitmapToGlideDrawableTranscoder(context), GlideDrawable::class.java) .decoder(FallbackGlideBitmapDecoder()) .encoder(BitmapEncoder(Bitmap.CompressFormat.PNG, 0)) .cacheDecoder(FileToStreamDecoder(StreamBitmapDecoder(context))) .diskCacheStrategy(DiskCacheStrategy.NONE) .load(new FallbackGlideParams(address)) .load(FallbackGlideParams(address)) // for some reason, following 2 lines fix loading issues. .dontAnimate() .override(mPictureSizeInPx, mPictureSizeInPx) .into(imageView); .override(pictureSizeInPx, pictureSizeInPx) .into(imageView) } private void loadContactPicture(Uri photoUri, final Address address, final ImageView imageView) { private fun loadContactPicture(photoUri: Uri?, address: Address, imageView: ImageView) { if (photoUri != null) { RequestListener<Uri, GlideDrawable> noPhotoListener = new RequestListener<Uri, GlideDrawable>() { @Override public boolean onException(Exception e, Uri model, Target<GlideDrawable> target, boolean isFirstResource) { loadFallbackPicture(address, imageView); return true; val noPhotoListener = object : RequestListener<Uri, GlideDrawable> { override fun onException( e: Exception, model: Uri, target: Target<GlideDrawable>, isFirstResource: Boolean ): Boolean { loadFallbackPicture(address, imageView) return true } @Override public boolean onResourceReady(GlideDrawable resource, Uri model, Target<GlideDrawable> target, boolean isFromMemoryCache, boolean isFirstResource) { return false; override fun onResourceReady( resource: GlideDrawable, model: Uri, target: Target<GlideDrawable>, isFromMemoryCache: Boolean, isFirstResource: Boolean ): Boolean { return false } } }; Glide.with(imageView.getContext()) Glide.with(imageView.context) .load(photoUri) .diskCacheStrategy(DiskCacheStrategy.NONE) .listener(noPhotoListener) // for some reason, following 2 lines fix loading issues. .dontAnimate() .override(mPictureSizeInPx, mPictureSizeInPx) .into(imageView); .override(pictureSizeInPx, pictureSizeInPx) .into(imageView) } else { loadFallbackPicture(address, imageView); loadFallbackPicture(address, imageView) } } public Bitmap loadContactPictureIcon(Recipient recipient) { return loadContactPicture(recipient.photoThumbnailUri, recipient.address); fun loadContactPictureIcon(recipient: Recipient): Bitmap? { return loadContactPicture(recipient.photoThumbnailUri, recipient.address) } @WorkerThread private Bitmap loadContactPicture(Uri photoUri, Address address) { FutureTarget<Bitmap> bitmapTarget; private fun loadContactPicture(photoUri: Uri?, address: Address): Bitmap? { val bitmapTarget: FutureTarget<Bitmap> if (photoUri != null) { bitmapTarget = Glide.with(context) .load(photoUri) .asBitmap() .diskCacheStrategy(DiskCacheStrategy.NONE) .dontAnimate() .into(mPictureSizeInPx, mPictureSizeInPx); .into(pictureSizeInPx, pictureSizeInPx) } else { bitmapTarget = Glide.with(context) .using(new FallbackGlideModelLoader(), FallbackGlideParams.class) .from(FallbackGlideParams.class) .as(Bitmap.class) .decoder(new FallbackGlideBitmapDecoder(context)) .encoder(new BitmapEncoder(CompressFormat.PNG, 0)) .cacheDecoder(new FileToStreamDecoder<>(new StreamBitmapDecoder(context))) .using(FallbackGlideModelLoader(), FallbackGlideParams::class.java) .from(FallbackGlideParams::class.java) .`as`(Bitmap::class.java) .decoder(FallbackGlideBitmapDecoder()) .encoder(BitmapEncoder(CompressFormat.PNG, 0)) .cacheDecoder(FileToStreamDecoder(StreamBitmapDecoder(context))) .diskCacheStrategy(DiskCacheStrategy.NONE) .load(new FallbackGlideParams(address)) .load(FallbackGlideParams(address)) .dontAnimate() .into(mPictureSizeInPx, mPictureSizeInPx); .into(pictureSizeInPx, pictureSizeInPx) } return loadIgnoringErors(bitmapTarget); return loadIgnoringErrors(bitmapTarget) } private class FallbackGlideBitmapDecoder implements ResourceDecoder<FallbackGlideParams, Bitmap> { private final Context context; FallbackGlideBitmapDecoder(Context context) { this.context = context; } private inner class FallbackGlideBitmapDecoder : ResourceDecoder<FallbackGlideParams, Bitmap> { override fun decode(source: FallbackGlideParams, width: Int, height: Int): Resource<Bitmap> { val pool = Glide.get(context).bitmapPool val bitmap: Bitmap = pool.getDirty(pictureSizeInPx, pictureSizeInPx, Bitmap.Config.ARGB_8888) ?: Bitmap.createBitmap(pictureSizeInPx, pictureSizeInPx, Bitmap.Config.ARGB_8888) @Override public Resource<Bitmap> decode(FallbackGlideParams source, int width, int height) throws IOException { BitmapPool pool = Glide.get(context).getBitmapPool(); Bitmap bitmap = pool.getDirty(mPictureSizeInPx, mPictureSizeInPx, Bitmap.Config.ARGB_8888); if (bitmap == null) { bitmap = Bitmap.createBitmap(mPictureSizeInPx, mPictureSizeInPx, Bitmap.Config.ARGB_8888); } contactLetterBitmapCreator.drawBitmap(bitmap, pictureSizeInPx, source.address) Address address = source.address; contactLetterBitmapCreator.drawBitmap(bitmap, mPictureSizeInPx, address); return BitmapResource.obtain(bitmap, pool); return BitmapResource.obtain(bitmap, pool) } @Override public String getId() { return "fallback-photo"; override fun getId(): String { return "fallback-photo" } } private class FallbackGlideParams { final Address address; FallbackGlideParams(Address address) { this.address = address; private inner class FallbackGlideParams(val address: Address) { val id: String get() = String.format(Locale.ROOT, "%s-%s", address.address, address.personal) } public String getId() { return String.format(Locale.ROOT, "%s-%s", address.getAddress(), address.getPersonal()); private inner class FallbackGlideModelLoader : ModelLoader<FallbackGlideParams, FallbackGlideParams> { override fun getResourceFetcher( model: FallbackGlideParams, width: Int, height: Int ): DataFetcher<FallbackGlideParams> = object : DataFetcher<FallbackGlideParams> { override fun loadData(priority: Priority): FallbackGlideParams = model override fun getId(): String = model.id override fun cleanup() = Unit override fun cancel() = Unit } } private class FallbackGlideModelLoader implements ModelLoader<FallbackGlideParams, FallbackGlideParams> { @Override public DataFetcher<FallbackGlideParams> getResourceFetcher(final FallbackGlideParams model, int width, int height) { return new DataFetcher<FallbackGlideParams>() { @Override public FallbackGlideParams loadData(Priority priority) throws Exception { return model; @WorkerThread private fun <T> loadIgnoringErrors(target: FutureTarget<T>): T? { return try { target.get() } catch (e: Exception) { null } @Override public void cleanup() { } @Override public String getId() { return model.getId(); } private fun Int.toDip(context: Context): Int = (this * context.resources.displayMetrics.density).toInt() @Override public void cancel() { companion object { /** * Resize the pictures to the following value (device-independent pixels). */ private const val PICTURE_SIZE = 40 } }; } } @WorkerThread @Nullable private <T> T loadIgnoringErors(FutureTarget<T> target) { try { return target.get(); } catch (Exception e) { return null; } } } Loading
app/ui/src/main/java/com/fsck/k9/activity/misc/ContactPicture.java +1 −1 Original line number Diff line number Diff line Loading @@ -12,6 +12,6 @@ public class ContactPicture { public static ContactPictureLoader getContactPictureLoader(Context context) { ContactLetterBitmapCreator contactLetterBitmapCreator = DI.get(ContactLetterBitmapCreator.class); return new ContactPictureLoader(context, contactLetterBitmapCreator); return new ContactPictureLoader(context.getApplicationContext(), contactLetterBitmapCreator); } }
app/ui/src/main/java/com/fsck/k9/contacts/ContactPictureLoader.kt +130 −170 Original line number Diff line number Diff line package com.fsck.k9.contacts; import java.io.IOException; import java.util.Locale; import android.content.Context; import android.content.res.Resources; import android.graphics.Bitmap; import android.graphics.Bitmap.CompressFormat; import android.net.Uri; import android.support.annotation.Nullable; import android.support.annotation.WorkerThread; import android.widget.ImageView; import com.bumptech.glide.Glide; import com.bumptech.glide.Priority; import com.bumptech.glide.load.ResourceDecoder; import com.bumptech.glide.load.data.DataFetcher; import com.bumptech.glide.load.engine.DiskCacheStrategy; import com.bumptech.glide.load.engine.Resource; import com.bumptech.glide.load.engine.bitmap_recycle.BitmapPool; import com.bumptech.glide.load.model.ModelLoader; import com.bumptech.glide.load.resource.bitmap.BitmapEncoder; import com.bumptech.glide.load.resource.bitmap.BitmapResource; import com.bumptech.glide.load.resource.bitmap.StreamBitmapDecoder; import com.bumptech.glide.load.resource.drawable.GlideDrawable; import com.bumptech.glide.load.resource.file.FileToStreamDecoder; import com.bumptech.glide.load.resource.transcode.BitmapToGlideDrawableTranscoder; import com.bumptech.glide.request.FutureTarget; import com.bumptech.glide.request.RequestListener; import com.bumptech.glide.request.target.Target; import com.fsck.k9.helper.Contacts; import com.fsck.k9.mail.Address; import com.fsck.k9.view.RecipientSelectView.Recipient; public class ContactPictureLoader { /** * Resize the pictures to the following value (device-independent pixels). */ private static final int PICTURE_SIZE = 40; private final Context context; private final ContactLetterBitmapCreator contactLetterBitmapCreator; private Contacts mContactsHelper; private int mPictureSizeInPx; public ContactPictureLoader(Context context, ContactLetterBitmapCreator contactLetterBitmapCreator) { this.context = context.getApplicationContext(); this.contactLetterBitmapCreator = contactLetterBitmapCreator; mContactsHelper = Contacts.getInstance(this.context); Resources resources = context.getResources(); float scale = resources.getDisplayMetrics().density; mPictureSizeInPx = (int) (PICTURE_SIZE * scale); } public void loadContactPicture(final Address address, final ImageView imageView) { Uri photoUri = mContactsHelper.getPhotoUri(address.getAddress()); loadContactPicture(photoUri, address, imageView); } public void loadContactPicture(Recipient recipient, ImageView imageView) { loadContactPicture(recipient.photoThumbnailUri, recipient.address, imageView); } private void loadFallbackPicture(Address address, ImageView imageView) { Context context = imageView.getContext(); package com.fsck.k9.contacts import android.content.Context import android.graphics.Bitmap import android.graphics.Bitmap.CompressFormat import android.net.Uri import android.support.annotation.WorkerThread import android.widget.ImageView import com.bumptech.glide.Glide import com.bumptech.glide.Priority import com.bumptech.glide.load.ResourceDecoder import com.bumptech.glide.load.data.DataFetcher import com.bumptech.glide.load.engine.DiskCacheStrategy import com.bumptech.glide.load.engine.Resource import com.bumptech.glide.load.model.ModelLoader import com.bumptech.glide.load.resource.bitmap.BitmapEncoder import com.bumptech.glide.load.resource.bitmap.BitmapResource import com.bumptech.glide.load.resource.bitmap.StreamBitmapDecoder import com.bumptech.glide.load.resource.drawable.GlideDrawable import com.bumptech.glide.load.resource.file.FileToStreamDecoder import com.bumptech.glide.load.resource.transcode.BitmapToGlideDrawableTranscoder import com.bumptech.glide.request.FutureTarget import com.bumptech.glide.request.RequestListener import com.bumptech.glide.request.target.Target import com.fsck.k9.helper.Contacts import com.fsck.k9.mail.Address import com.fsck.k9.view.RecipientSelectView.Recipient import java.util.Locale class ContactPictureLoader( private val context: Context, private val contactLetterBitmapCreator: ContactLetterBitmapCreator ) { private val contactsHelper: Contacts = Contacts.getInstance(context) private val pictureSizeInPx: Int = PICTURE_SIZE.toDip(context) fun loadContactPicture(address: Address, imageView: ImageView) { val photoUri = contactsHelper.getPhotoUri(address.address) loadContactPicture(photoUri, address, imageView) } fun loadContactPicture(recipient: Recipient, imageView: ImageView) { loadContactPicture(recipient.photoThumbnailUri, recipient.address, imageView) } private fun loadFallbackPicture(address: Address, imageView: ImageView) { val context = imageView.context Glide.with(context) .using(new FallbackGlideModelLoader(), FallbackGlideParams.class) .from(FallbackGlideParams.class) .as(Bitmap.class) .transcode(new BitmapToGlideDrawableTranscoder(context), GlideDrawable.class) .decoder(new FallbackGlideBitmapDecoder(context)) .encoder(new BitmapEncoder(Bitmap.CompressFormat.PNG, 0)) .cacheDecoder(new FileToStreamDecoder<>(new StreamBitmapDecoder(context))) .using(FallbackGlideModelLoader(), FallbackGlideParams::class.java) .from(FallbackGlideParams::class.java) .`as`(Bitmap::class.java) .transcode(BitmapToGlideDrawableTranscoder(context), GlideDrawable::class.java) .decoder(FallbackGlideBitmapDecoder()) .encoder(BitmapEncoder(Bitmap.CompressFormat.PNG, 0)) .cacheDecoder(FileToStreamDecoder(StreamBitmapDecoder(context))) .diskCacheStrategy(DiskCacheStrategy.NONE) .load(new FallbackGlideParams(address)) .load(FallbackGlideParams(address)) // for some reason, following 2 lines fix loading issues. .dontAnimate() .override(mPictureSizeInPx, mPictureSizeInPx) .into(imageView); .override(pictureSizeInPx, pictureSizeInPx) .into(imageView) } private void loadContactPicture(Uri photoUri, final Address address, final ImageView imageView) { private fun loadContactPicture(photoUri: Uri?, address: Address, imageView: ImageView) { if (photoUri != null) { RequestListener<Uri, GlideDrawable> noPhotoListener = new RequestListener<Uri, GlideDrawable>() { @Override public boolean onException(Exception e, Uri model, Target<GlideDrawable> target, boolean isFirstResource) { loadFallbackPicture(address, imageView); return true; val noPhotoListener = object : RequestListener<Uri, GlideDrawable> { override fun onException( e: Exception, model: Uri, target: Target<GlideDrawable>, isFirstResource: Boolean ): Boolean { loadFallbackPicture(address, imageView) return true } @Override public boolean onResourceReady(GlideDrawable resource, Uri model, Target<GlideDrawable> target, boolean isFromMemoryCache, boolean isFirstResource) { return false; override fun onResourceReady( resource: GlideDrawable, model: Uri, target: Target<GlideDrawable>, isFromMemoryCache: Boolean, isFirstResource: Boolean ): Boolean { return false } } }; Glide.with(imageView.getContext()) Glide.with(imageView.context) .load(photoUri) .diskCacheStrategy(DiskCacheStrategy.NONE) .listener(noPhotoListener) // for some reason, following 2 lines fix loading issues. .dontAnimate() .override(mPictureSizeInPx, mPictureSizeInPx) .into(imageView); .override(pictureSizeInPx, pictureSizeInPx) .into(imageView) } else { loadFallbackPicture(address, imageView); loadFallbackPicture(address, imageView) } } public Bitmap loadContactPictureIcon(Recipient recipient) { return loadContactPicture(recipient.photoThumbnailUri, recipient.address); fun loadContactPictureIcon(recipient: Recipient): Bitmap? { return loadContactPicture(recipient.photoThumbnailUri, recipient.address) } @WorkerThread private Bitmap loadContactPicture(Uri photoUri, Address address) { FutureTarget<Bitmap> bitmapTarget; private fun loadContactPicture(photoUri: Uri?, address: Address): Bitmap? { val bitmapTarget: FutureTarget<Bitmap> if (photoUri != null) { bitmapTarget = Glide.with(context) .load(photoUri) .asBitmap() .diskCacheStrategy(DiskCacheStrategy.NONE) .dontAnimate() .into(mPictureSizeInPx, mPictureSizeInPx); .into(pictureSizeInPx, pictureSizeInPx) } else { bitmapTarget = Glide.with(context) .using(new FallbackGlideModelLoader(), FallbackGlideParams.class) .from(FallbackGlideParams.class) .as(Bitmap.class) .decoder(new FallbackGlideBitmapDecoder(context)) .encoder(new BitmapEncoder(CompressFormat.PNG, 0)) .cacheDecoder(new FileToStreamDecoder<>(new StreamBitmapDecoder(context))) .using(FallbackGlideModelLoader(), FallbackGlideParams::class.java) .from(FallbackGlideParams::class.java) .`as`(Bitmap::class.java) .decoder(FallbackGlideBitmapDecoder()) .encoder(BitmapEncoder(CompressFormat.PNG, 0)) .cacheDecoder(FileToStreamDecoder(StreamBitmapDecoder(context))) .diskCacheStrategy(DiskCacheStrategy.NONE) .load(new FallbackGlideParams(address)) .load(FallbackGlideParams(address)) .dontAnimate() .into(mPictureSizeInPx, mPictureSizeInPx); .into(pictureSizeInPx, pictureSizeInPx) } return loadIgnoringErors(bitmapTarget); return loadIgnoringErrors(bitmapTarget) } private class FallbackGlideBitmapDecoder implements ResourceDecoder<FallbackGlideParams, Bitmap> { private final Context context; FallbackGlideBitmapDecoder(Context context) { this.context = context; } private inner class FallbackGlideBitmapDecoder : ResourceDecoder<FallbackGlideParams, Bitmap> { override fun decode(source: FallbackGlideParams, width: Int, height: Int): Resource<Bitmap> { val pool = Glide.get(context).bitmapPool val bitmap: Bitmap = pool.getDirty(pictureSizeInPx, pictureSizeInPx, Bitmap.Config.ARGB_8888) ?: Bitmap.createBitmap(pictureSizeInPx, pictureSizeInPx, Bitmap.Config.ARGB_8888) @Override public Resource<Bitmap> decode(FallbackGlideParams source, int width, int height) throws IOException { BitmapPool pool = Glide.get(context).getBitmapPool(); Bitmap bitmap = pool.getDirty(mPictureSizeInPx, mPictureSizeInPx, Bitmap.Config.ARGB_8888); if (bitmap == null) { bitmap = Bitmap.createBitmap(mPictureSizeInPx, mPictureSizeInPx, Bitmap.Config.ARGB_8888); } contactLetterBitmapCreator.drawBitmap(bitmap, pictureSizeInPx, source.address) Address address = source.address; contactLetterBitmapCreator.drawBitmap(bitmap, mPictureSizeInPx, address); return BitmapResource.obtain(bitmap, pool); return BitmapResource.obtain(bitmap, pool) } @Override public String getId() { return "fallback-photo"; override fun getId(): String { return "fallback-photo" } } private class FallbackGlideParams { final Address address; FallbackGlideParams(Address address) { this.address = address; private inner class FallbackGlideParams(val address: Address) { val id: String get() = String.format(Locale.ROOT, "%s-%s", address.address, address.personal) } public String getId() { return String.format(Locale.ROOT, "%s-%s", address.getAddress(), address.getPersonal()); private inner class FallbackGlideModelLoader : ModelLoader<FallbackGlideParams, FallbackGlideParams> { override fun getResourceFetcher( model: FallbackGlideParams, width: Int, height: Int ): DataFetcher<FallbackGlideParams> = object : DataFetcher<FallbackGlideParams> { override fun loadData(priority: Priority): FallbackGlideParams = model override fun getId(): String = model.id override fun cleanup() = Unit override fun cancel() = Unit } } private class FallbackGlideModelLoader implements ModelLoader<FallbackGlideParams, FallbackGlideParams> { @Override public DataFetcher<FallbackGlideParams> getResourceFetcher(final FallbackGlideParams model, int width, int height) { return new DataFetcher<FallbackGlideParams>() { @Override public FallbackGlideParams loadData(Priority priority) throws Exception { return model; @WorkerThread private fun <T> loadIgnoringErrors(target: FutureTarget<T>): T? { return try { target.get() } catch (e: Exception) { null } @Override public void cleanup() { } @Override public String getId() { return model.getId(); } private fun Int.toDip(context: Context): Int = (this * context.resources.displayMetrics.density).toInt() @Override public void cancel() { companion object { /** * Resize the pictures to the following value (device-independent pixels). */ private const val PICTURE_SIZE = 40 } }; } } @WorkerThread @Nullable private <T> T loadIgnoringErors(FutureTarget<T> target) { try { return target.get(); } catch (Exception e) { return null; } } }