Add placeholder drawable for asyncDrawableLoader

This commit is contained in:
Dimitry Ivanov 2019-03-15 14:39:15 +03:00
parent 519c5c98e5
commit 50bf5b341a
4 changed files with 79 additions and 6 deletions

View File

@ -39,6 +39,26 @@ public class AsyncDrawable extends Drawable {
this.loader = loader; this.loader = loader;
this.imageSizeResolver = imageSizeResolver; this.imageSizeResolver = imageSizeResolver;
this.imageSize = imageSize; this.imageSize = imageSize;
final Drawable placeholder = loader.placeholder();
if (placeholder != null) {
// process placeholder bounds
final Rect bounds = placeholder.getBounds();
if (bounds.isEmpty()) {
// set intrinsic bounds
final Rect rect = new Rect(
0,
0,
placeholder.getIntrinsicWidth(),
placeholder.getIntrinsicHeight());
placeholder.setBounds(rect);
setBounds(rect);
}
// apply placeholder immediately if we have one
setResult(placeholder);
}
} }
@NonNull @NonNull
@ -66,6 +86,15 @@ public class AsyncDrawable extends Drawable {
// if not null -> means we are attached // if not null -> means we are attached
if (callback != null) { if (callback != null) {
// as we have a placeholder now, it's important to check it our placeholder
// has a proper callback at this point. This is not required in most cases,
// as placeholder should be static, but if it's not -> it can operate as usual
if (result != null
&& result.getCallback() == null) {
result.setCallback(callback);
}
loader.load(destination, this); loader.load(destination, this);
} else { } else {
if (result != null) { if (result != null) {

View File

@ -12,6 +12,14 @@ import java.util.concurrent.Executors;
public abstract class AsyncDrawableLoader { public abstract class AsyncDrawableLoader {
/**
* @since 3.0.0
*/
public interface DrawableProvider {
@Nullable
Drawable provide();
}
/** /**
* @since 3.0.0 * @since 3.0.0
*/ */
@ -33,6 +41,8 @@ public abstract class AsyncDrawableLoader {
public abstract void cancel(@NonNull String destination); public abstract void cancel(@NonNull String destination);
@Nullable
public abstract Drawable placeholder();
public static class Builder { public static class Builder {
@ -40,7 +50,8 @@ public abstract class AsyncDrawableLoader {
final Map<String, SchemeHandler> schemeHandlers = new HashMap<>(3); final Map<String, SchemeHandler> schemeHandlers = new HashMap<>(3);
final Map<String, MediaDecoder> mediaDecoders = new HashMap<>(3); final Map<String, MediaDecoder> mediaDecoders = new HashMap<>(3);
MediaDecoder defaultMediaDecoder; MediaDecoder defaultMediaDecoder;
Drawable errorDrawable; DrawableProvider placeholderDrawableProvider;
DrawableProvider errorDrawableProvider;
@NonNull @NonNull
public Builder executorService(@NonNull ExecutorService executorService) { public Builder executorService(@NonNull ExecutorService executorService) {
@ -94,9 +105,21 @@ public abstract class AsyncDrawableLoader {
return this; return this;
} }
/**
* @since 3.0.0
*/
@NonNull @NonNull
public Builder errorDrawable(Drawable errorDrawable) { public Builder placeholderDrawableProvider(@NonNull DrawableProvider placeholderDrawableProvider) {
this.errorDrawable = errorDrawable; this.placeholderDrawableProvider = placeholderDrawableProvider;
return this;
}
/**
* @since 3.0.0
*/
@NonNull
public Builder errorDrawableProvider(@NonNull DrawableProvider errorDrawableProvider) {
this.errorDrawableProvider = errorDrawableProvider;
return this; return this;
} }

View File

@ -5,6 +5,7 @@ import android.net.Uri;
import android.os.Handler; import android.os.Handler;
import android.os.Looper; import android.os.Looper;
import android.support.annotation.NonNull; import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
@ -20,7 +21,8 @@ class AsyncDrawableLoaderImpl extends AsyncDrawableLoader {
private final Map<String, SchemeHandler> schemeHandlers; private final Map<String, SchemeHandler> schemeHandlers;
private final Map<String, MediaDecoder> mediaDecoders; private final Map<String, MediaDecoder> mediaDecoders;
private final MediaDecoder defaultMediaDecoder; private final MediaDecoder defaultMediaDecoder;
private final Drawable errorDrawable; private final DrawableProvider placeholderDrawableProvider;
private final DrawableProvider errorDrawableProvider;
private final Handler mainThread; private final Handler mainThread;
@ -31,7 +33,8 @@ class AsyncDrawableLoaderImpl extends AsyncDrawableLoader {
this.schemeHandlers = builder.schemeHandlers; this.schemeHandlers = builder.schemeHandlers;
this.mediaDecoders = builder.mediaDecoders; this.mediaDecoders = builder.mediaDecoders;
this.defaultMediaDecoder = builder.defaultMediaDecoder; this.defaultMediaDecoder = builder.defaultMediaDecoder;
this.errorDrawable = builder.errorDrawable; this.placeholderDrawableProvider = builder.placeholderDrawableProvider;
this.errorDrawableProvider = builder.errorDrawableProvider;
this.mainThread = new Handler(Looper.getMainLooper()); this.mainThread = new Handler(Looper.getMainLooper());
} }
@ -49,6 +52,14 @@ class AsyncDrawableLoaderImpl extends AsyncDrawableLoader {
} }
} }
@Nullable
@Override
public Drawable placeholder() {
return placeholderDrawableProvider != null
? placeholderDrawableProvider.provide()
: null;
}
private Future<?> execute(@NonNull final String destination, @NonNull AsyncDrawable drawable) { private Future<?> execute(@NonNull final String destination, @NonNull AsyncDrawable drawable) {
final WeakReference<AsyncDrawable> reference = new WeakReference<AsyncDrawable>(drawable); final WeakReference<AsyncDrawable> reference = new WeakReference<AsyncDrawable>(drawable);
@ -109,7 +120,9 @@ class AsyncDrawableLoaderImpl extends AsyncDrawableLoader {
// if result is null, we assume it's an error // if result is null, we assume it's an error
if (result == null) { if (result == null) {
result = errorDrawable; result = errorDrawableProvider != null
? errorDrawableProvider.provide()
: null;
} }
if (result != null) { if (result != null) {

View File

@ -1,6 +1,8 @@
package ru.noties.markwon.image; package ru.noties.markwon.image;
import android.graphics.drawable.Drawable;
import android.support.annotation.NonNull; import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
class AsyncDrawableLoaderNoOp extends AsyncDrawableLoader { class AsyncDrawableLoaderNoOp extends AsyncDrawableLoader {
@Override @Override
@ -12,4 +14,10 @@ class AsyncDrawableLoaderNoOp extends AsyncDrawableLoader {
public void cancel(@NonNull String destination) { public void cancel(@NonNull String destination) {
} }
@Nullable
@Override
public Drawable placeholder() {
return null;
}
} }