glide icon indicating copy to clipboard operation
glide copied to clipboard

Multiple executions of the same failed target when backgrounding

Open mattleibow opened this issue 2 years ago • 1 comments

Glide Version: 4.12.0

Integration libraries: n/a

Device/Android Version: Pixel 5 - API 30 emulator

Issue details / Repro steps / Use case background:

If an image fails to load (does not exist) then pausing and resuming the app triggers the load again

Glide load line / GlideModule (if any) / list Adapter code (if any):

package com.example.myapplication;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;

import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;

import com.bumptech.glide.Glide;
import com.bumptech.glide.RequestManager;
import com.bumptech.glide.request.target.CustomViewTarget;
import com.bumptech.glide.request.transition.Transition;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Button btn = findViewById(R.id.my_button);
        ImageView img = findViewById(R.id.my_image);

        btn.setOnClickListener(v -> {
            RequestManager glide = Glide.with(img);
            MyCustomViewTarget target = new MyCustomViewTarget(img, glide);
            glide
                .load("bad_file_name.png")
                .into(target);
        });
    }
}

class MyCustomViewTarget extends CustomViewTarget<ImageView, Drawable> {
    private final RequestManager requestManager;
    private int counter;

    public MyCustomViewTarget(@NonNull ImageView view, RequestManager requestManager) {
        super(view);
        this.requestManager = requestManager;
        Log.e("MY_APP", "new MyCustomViewTarget");
    }

    @Override
    protected void onResourceCleared(@Nullable Drawable placeholder) {
    }

    @Override
    public void onLoadFailed(@Nullable Drawable errorDrawable) {
        Log.e("MY_APP", "onLoadFailed: " + counter++);
    }

    @Override
    public void onResourceReady(@NonNull Drawable resource, @Nullable Transition<? super Drawable> transition) {
        Log.e("MY_APP", "onResourceReady");
        this.view.setImageDrawable(resource);
    }
}

Layout XML:

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">
        <ImageView
            android:layout_width="200dp"
            android:layout_height="200dp"
            android:id="@+id/my_image" />
        <Button
            android:layout_width="200dp"
            android:layout_height="50dp"
            android:text="Hello"
            android:id="@+id/my_button" />
    </LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>

https://user-images.githubusercontent.com/1096616/166216185-e2a846e1-ea54-4126-9fa7-6a7f573ef150.mp4

mattleibow avatar May 02 '22 09:05 mattleibow

I think Bug/Feature is exactly the right way to describe this :).

As a general rule Glide's Targets do not complete once. One example where this is more clearly a feature is when Glide restarts failed requests when it thinks the app might have regained connectivity.

You can opt-out of the lifecycle by using the application context for Glide.with, but that's not free because it removes other lifecycle integrations. It also doesn't remove the restart-on-connectivity-change behavior.

I could be convinced either way I guess. Restating failures for loads in normal Android Views seems pretty harmless. But when done for other frameworks or reasons it's easy to see why it's not what people expect.

sjudd avatar Aug 26 '22 16:08 sjudd