Closed Mooop closed 5 months ago
Resolve the issue by implementing the LifecycleObserver interface to receive callbacks.
sample code:
public class ATarget extends CustomTarget
final String TAG = ATarget.class.getSimpleName();
private final TextView view;
private final SpannableStringBuilder builder;
private final int start;
private final int end;
private final CompositeDisposable disposable = new CompositeDisposable();
private GifDrawable gif;
private Callback callback = new Callback() {
@Override
public void invalidateDrawable(@NonNull Drawable who) {
view.invalidate();
}
@Override
public void scheduleDrawable(@NonNull Drawable who, @NonNull Runnable what,
long when) {
view.postDelayed(what, when);
}
@Override
public void unscheduleDrawable(@NonNull Drawable who, @NonNull Runnable what) {
view.removeCallbacks(what);
}
};
/**
* Constructor that defaults {@code waitForLayout} to {@code false}.
*
* @param view
*/
public ATarget(@NonNull TextView view, SpannableStringBuilder builder, int start, int end) {
this.view = view;
this.builder = builder;
this.start = start;
this.end = end;
if (view.getContext() instanceof AppCompatActivity) {
AppCompatActivity compatActivity = (AppCompatActivity) view.getContext();
compatActivity.getLifecycle().addObserver(this);
}
}
@Override
public void onResourceReady(@NonNull GifDrawable resource,
@Nullable Transition<? super GifDrawable> transition) {
resource.setBounds(0, 0, resource.getIntrinsicWidth(), resource.getIntrinsicHeight());
resource.setCallback(callback);
resource.setLoopCount(GifDrawable.LOOP_FOREVER);
resource.start();
gif = resource;
builder.setSpan(new CustomImageSpan(resource, ImageSpan.ALIGN_BOTTOM), start, end,
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
view.setText(builder);
}
@OnLifecycleEvent(Event.ON_RESUME)
void activityOnResume() {
if (null != gif && !gif.isRunning()) {
gif.start();
Log.d(TAG, "activityOnResume");
}
}
@OnLifecycleEvent(Event.ON_STOP)
void activityOnStop() {
if (null != gif) {
gif.stop();
Log.d(TAG, "activityOnStop");
}
}
@OnLifecycleEvent(Event.ON_DESTROY)
void activityOnDestroy() {
if (null != gif) {
gif.stop();
gif.setCallback(null);
callback = null;
}
}
@Override
public void onLoadCleared(@Nullable Drawable placeholder) {
Log.e(TAG,"onLoadCleared");
if (null != gif) {
gif.stop();
}
}
@Override
public void onDestroy() {
super.onDestroy();
}
@Override
public void onStart() {
super.onStart();
}
@Override
public void onStop() {
super.onStop();
}
static class CustomImageSpan extends ImageSpan {
public CustomImageSpan(@NonNull Drawable drawable, int verticalAlignment) {
super(drawable, verticalAlignment);
}
@Override
public Drawable getDrawable() {
return super.getDrawable();
}
public void draw(Canvas canvas, CharSequence text, int start, int end, float x,
int top, int y, int bottom, Paint paint) {
Drawable drawable = getDrawable();
Paint.FontMetricsInt fontMetricsInt = paint.getFontMetricsInt();
int transY = y + fontMetricsInt.descent / 2 - drawable.getBounds().bottom;
canvas.save();
canvas.translate(x, transY);
drawable.draw(canvas);
canvas.restore();
}
}
}
Are there any other better methods to solve the problem?
Using Glide to load GIFs, when my application switches from the foreground to the background and repeats this operation several times, the LifecycleListener of the CustomTarget no longer receives callbacks.
Google Pixel4A, Android 13,API 33 Glide version: 4.15.1. Context:Fragment/Activity
sample code:
public class ATarget extends CustomTarget {
}