-
-
Notifications
You must be signed in to change notification settings - Fork 314
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
How to implement custom AsyncDrawableLoader #109
Comments
You could use the Image OkHttp that includes a factory overload method which will allow you to configure OkHttp client behaviour for caching. However I wanted to use glide instead, so I just tried to create my own plugin using the source code provided for the OkHttp implementation |
Yeah, I want to use glide too. I just cannot find the way to use a custom AsyncDrawableLoader. Could you please show me some code? |
Hello @yjouyang ! Default image loader indeed doesn't have cache. But, as @wax911 has mentioned, you can use // configure OkHttpClient
final OkHttpClient okHttpClient = obtainHttpClient();
final Markwon markwon = Markwon.builder(context)
.usePlugin(ImagesPlugin.createWithAssets(context))
.usePlugin(OkHttpImagesPlugin.create(okHttpClient))
.build(); As for creating own implementation of
it still could use some attention and it is one of the primary targets for future improvement. Anyway, if current set of features doesn't work for you, we can introduce a way to provide own implementation of loader, for example like this: .usePlugin(new AbstractMarkwonPlugin() {
@Override
public void configureImages(@NonNull AsyncDrawableLoader.Builder builder) {
builder.implementation(new GlideImageLoader(context));
}
}) One down-side is that all configured things will be ignored (scheme handlers, media decoders, placeholder, error drawables, etc), but maybe it's not that bad. If you find it interesting I can deploy a snapshot version with this feature implemented |
I'm using Glide too, would like to test such snapshot. |
@yjouyang meanwhile, came up with this class MarkwonGlidePlugin(private val ctx: Context): AbstractMarkwonPlugin() {
companion object {
fun create(ctx: Context): MarkwonGlidePlugin {
return MarkwonGlidePlugin(ctx)
}
}
inner class GlideHandler: SchemeHandler() {
override fun handle(raw: String, uri: Uri): ImageItem? {
val glide = Glide.with(ctx)
.downloadOnly()
.load(raw)
.apply(RequestOptions()
.placeholder(R.drawable.image)
.error(R.drawable.image_broken)
.centerInside())
.submit()
return ImageItem("image/*", glide.get().inputStream())
}
}
override fun configureImages(builder: AsyncDrawableLoader.Builder) {
builder.addSchemeHandler(NetworkSchemeHandler.SCHEME_HTTP, GlideHandler())
builder.addSchemeHandler(NetworkSchemeHandler.SCHEME_HTTPS, GlideHandler())
}
} |
@noties |
@Adonai Appreciate it! I'll try this |
I've just pushed .usePlugin(new AbstractMarkwonPlugin() {
@Override
public void configureImages(@NonNull AsyncDrawableLoader.Builder builder) {
builder.implementation(new GlideLoader());
}
}) I haven't included actual private static class GlideImagePlugin extends AbstractMarkwonPlugin {
@NonNull
public static GlideImagePlugin create(@NonNull Context context) {
return new GlideImagePlugin(context);
}
private final Context context;
GlideImagePlugin(@NonNull Context context) {
this.context = context;
}
@Override
public void configureImages(@NonNull AsyncDrawableLoader.Builder builder) {
builder.implementation(new GlideAsyncDrawableLoader(context));
}
@NonNull
@Override
public Priority priority() {
return Priority.after(ImagesPlugin.class);
}
private static class GlideAsyncDrawableLoader extends AsyncDrawableLoader {
private final Context context;
private final Map<String, WeakReference<AsyncDrawableTarget>> cache
= Collections.synchronizedMap(new HashMap<String, WeakReference<AsyncDrawableTarget>>(3));
GlideAsyncDrawableLoader(@NonNull Context context) {
this.context = context;
}
@Override
public void load(@NonNull String destination, @NonNull AsyncDrawable drawable) {
final AsyncDrawableTarget target = new AsyncDrawableTarget(drawable);
Glide.with(context)
.load(destination)
.into(target);
cache.put(destination, new WeakReference<AsyncDrawableTarget>(target));
}
@Override
public void cancel(@NonNull String destination) {
final WeakReference<AsyncDrawableTarget> reference = cache.remove(destination);
final AsyncDrawableTarget target = reference != null
? reference.get()
: null;
if (target != null) {
Glide.with(context).clear(target);
target.drawable.clearResult();
}
}
@Nullable
@Override
public Drawable placeholder() {
// we can also return placeholder here instead of specifying for Glide
return null;
}
private static class AsyncDrawableTarget extends CustomTarget<Drawable> {
private final AsyncDrawable drawable;
AsyncDrawableTarget(@NonNull AsyncDrawable drawable) {
this.drawable = drawable;
}
@Override
public void onResourceReady(@NonNull Drawable resource, @Nullable Transition<? super Drawable> transition) {
// it's important to set resource bounds here
DrawableUtils.applyIntrinsicBoundsIfEmpty(resource);
drawable.setResult(resource);
}
@Override
public void onLoadStarted(@Nullable Drawable placeholder) {
if (placeholder != null) {
DrawableUtils.applyIntrinsicBoundsIfEmpty(placeholder);
drawable.setResult(placeholder);
}
}
@Override
public void onLoadFailed(@Nullable Drawable errorDrawable) {
if (errorDrawable != null) {
DrawableUtils.applyIntrinsicBoundsIfEmpty(errorDrawable);
drawable.setResult(errorDrawable);
}
}
@Override
public void onLoadCleared(@Nullable Drawable placeholder) {
drawable.clearResult();
}
}
}
} I have tested it and it works for regular images, but somehow GIF and SVG are not loaded ( @Adonai it's a possible solution, but it doesn't handle different from plain images content-types (GIF, SVG, etc). So they will most likely fail. Of cause it's fine, if you won't have such images. Anyway, if some one would want to create a special artifact with Glide image loading (in a form of a plugin), pull request is welcome |
@noties Good job! |
3.0.1 * Add `AsyncDrawableLoader.Builder#implementation` method (#109) * AsyncDrawable allow placeholder to have independent size (#115) * `addFactory` method for MarkwonSpansFactory * Add optional spans for list blocks (bullet and ordered) * AsyncDrawable placeholder bounds fix * SpannableBuilder setSpans allow array of arrays * Add `requireFactory` method to MarkwonSpansFactory * Add DrawableUtils
With version 3.0, how could I implement a custom AsyncDrawableLoader since the built-in one seems doesn't have cache
The text was updated successfully, but these errors were encountered: