diff --git a/CHANGELOG.md b/CHANGELOG.md index ab7a9ce0..df2cd26e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ * Add `requirePlugin(Class)` and `getPlugins` for `Markwon` instance * TablePlugin -> defer table invalidation (via `View.post`), so only one invalidation happens with each draw-call +* AsyncDrawableSpan -> defer invalidation # 4.0.2 * Fix `JLatexMathPlugin` formula placeholder (cannot have line breaks) ([#149]) diff --git a/markwon-core/src/main/java/io/noties/markwon/image/AsyncDrawableScheduler.java b/markwon-core/src/main/java/io/noties/markwon/image/AsyncDrawableScheduler.java index a7d664e3..ad33ca06 100644 --- a/markwon-core/src/main/java/io/noties/markwon/image/AsyncDrawableScheduler.java +++ b/markwon-core/src/main/java/io/noties/markwon/image/AsyncDrawableScheduler.java @@ -57,11 +57,14 @@ public abstract class AsyncDrawableScheduler { textView.setTag(R.id.markwon_drawables_scheduler, listener); } + // @since 4.1.0-SNAPSHOT + final DrawableCallbackImpl.Invalidator invalidator = new TextViewInvalidator(textView); + AsyncDrawable drawable; for (AsyncDrawableSpan span : spans) { drawable = span.getDrawable(); - drawable.setCallback2(new DrawableCallbackImpl(textView, drawable.getBounds())); + drawable.setCallback2(new DrawableCallbackImpl(textView, invalidator, drawable.getBounds())); } } } @@ -109,11 +112,23 @@ public abstract class AsyncDrawableScheduler { private static class DrawableCallbackImpl implements Drawable.Callback { + // @since 4.1.0-SNAPSHOT + // interface to be used when bounds change and view must be invalidated + interface Invalidator { + void invalidate(); + } + private final TextView view; + private final Invalidator invalidator; // @since 4.1.0-SNAPSHOT + private Rect previousBounds; - DrawableCallbackImpl(TextView view, Rect initialBounds) { + DrawableCallbackImpl( + @NonNull TextView view, + @NonNull Invalidator invalidator, + Rect initialBounds) { this.view = view; + this.invalidator = invalidator; this.previousBounds = new Rect(initialBounds); } @@ -136,8 +151,10 @@ public abstract class AsyncDrawableScheduler { // but if the size has changed, then we need to update the whole layout... if (!previousBounds.equals(rect)) { - // the only method that seems to work when bounds have changed - view.setText(view.getText()); + // @since 4.1.0-SNAPSHOT + // invalidation moved to upper level (so invalidation can be deferred, + // and multiple calls combined) + invalidator.invalidate(); previousBounds = new Rect(rect); } else { @@ -156,4 +173,24 @@ public abstract class AsyncDrawableScheduler { view.removeCallbacks(what); } } + + private static class TextViewInvalidator implements DrawableCallbackImpl.Invalidator, Runnable { + + private final TextView textView; + + TextViewInvalidator(@NonNull TextView textView) { + this.textView = textView; + } + + @Override + public void invalidate() { + textView.removeCallbacks(this); + textView.post(this); + } + + @Override + public void run() { + textView.setText(textView.getText()); + } + } }