Definir a visibilidade da barra de progresso após a conclusão do carregamento da imagem usando a biblioteca Glide

90

Olá, quero ter uma barra de progresso para a imagem que será exibida durante o carregamento da imagem, mas quando o carregamento da imagem for concluído, quero defini-la como desaparecido. Anteriormente, eu estava usando a biblioteca de Picasso para isso. Mas não sei como usá-lo com a biblioteca Glide. Tenho ideia que existe alguma função de recurso pronto, mas não sei como usá-la. Alguém pode me ajudar?

Código para a Biblioteca Picasso

Picasso.with(mcontext).load(imgLinkArray.get(position).mUrlLink)
       .into(imageView, new Callback() {
           @Override
           public void onSuccess() {
               progressBar.setVisibility(View.GONE);
           }

           @Override
           public void onError() {
           }
        })
;

Agora, como posso fazer isso com o Glide?

Glide.with(mcontext).load(imgLinkArray.get(position).mUrlLink)
     .into(imageView);

Eu consigo carregar a imagem com o Glide, mas como posso escrever progressBar.setVisibility(View.GONE);em algum lugar no código se a imagem for carregada?

HariRam
fonte
2
Por que você mudou sua biblioteca? Picasso é ótimo.
tasomaníaco
Eu também recomendaria continuar com o Picasso, a menos que você tenha um bom motivo para mudar de biblioteca
Chris,

Respostas:

232

A pergunta é bastante antiga, e não sei qual era a situação do glide naquela época, mas agora pode ser facilmente feita com o ouvinte (não como proposto na resposta escolhida como correta).

progressBar.setVisibility(View.VISIBLE);
Glide.with(getActivity())
     .load(args.getString(IMAGE_TO_SHOW))
     .listener(new RequestListener<String, GlideDrawable>() {
         @Override
         public boolean onException(Exception e, String model, Target<GlideDrawable> target, boolean isFirstResource) {
             return false;
         }

         @Override
         public boolean onResourceReady(GlideDrawable resource, String model, Target<GlideDrawable> target, boolean isFromMemoryCache, boolean isFirstResource) {
             progressBar.setVisibility(View.GONE);
             return false;
         }
     })
     .into(imageFrame)
;

Você retorna true se deseja manipular coisas como animações por conta própria e false se deseja que o glide manipula para você.

Yaroslav
fonte
13
Considere esconder o progressBarin onExceptiontambém, caso contrário ele girará indefinidamente, dando falsas esperanças. Uma vez que onExceptioné chamado de Glide não fará nada além de definir o que é passado para .error().
TWiStErRob
2
Isso pode resultar em uma NullPointerException se você deixar o Fragment / Activity antes do carregamento da imagem.
aProperFox
1
Não estou agitando você para criar ouvintes de classe interna, apenas a maneira mais concisa de mostrar uma ferramenta para realizar a tarefa.
Yaroslav,
1
Claro, resolvi isso adicionando uma chamada em onDestroyVIew () antes da super chamada para dizer Glide.clear (yourImageView)
aProperFox
7
NOTA: .listenerdeve ser chamado antes.into()
Ahmed Mostafa
31

Se você quiser fazer isso no KOTLIN, pode tentar desta forma:

    Glide.with(context)
            .load(url)
            .listener(object : RequestListener<Drawable> {
                override fun onLoadFailed(e: GlideException?, model: Any?, target: Target<Drawable>?, isFirstResource: Boolean): Boolean {
                    //TODO: something on exception
                }
                override fun onResourceReady(resource: Drawable?, model: Any?, target: Target<Drawable>?, dataSource: DataSource?, isFirstResource: Boolean): Boolean {
                    Log.d(TAG, "OnResourceReady")
                    //do something when picture already loaded
                    return false
                }
            })
            .into(imgView)
Paulina
fonte
7
Também é necessário importar o alvo:import com.bumptech.glide.request.target.Target
Gibolt
@Gibolt isso estava me incomodando por 10 minutos direto
johnrao07
17

Minha resposta foi baseada em APIs desatualizadas. Veja aqui a resposta mais atualizada.

Bryan Sills
fonte
.listener()é melhor porque você receberá mais informações sobre sua carga (modelo, cache de memória, ...) para que seja mais fácil decidir uma lógica mais personalizada. RequestListenertambém é mais estável, substituir o qual Targetcriar não proporcionará o benefício de futuras correções. Você também pode criar facilmente um VisibilityListener<T, R>que pode reutilizar em diferentes contextos.
TWiStErRob
10

Em exceção, coloque uma condição para mostrar novamente o ProgressBar

 Glide.with(context)
    .load(image_url)
    .listener(new RequestListener<String, GlideDrawable>() {
        @Override
        public boolean onException(Exception e, String model, Target<GlideDrawable> target, boolean isFirstResource) {
            if(e instanceof UnknownHostException)
                progressBar.setVisibility(View.VISIBLE);
            return false;
        }

        @Override
        public boolean onResourceReady(GlideDrawable resource, String model, Target<GlideDrawable> target, boolean isFromMemoryCache, boolean isFirstResource) {
            progressBar.setVisibility(View.GONE);
            return false;
        }
    })
    .into(imageView);
Alex Zaraos
fonte
8

A solução acima funciona muito bem para mim também, mas quando eu uso asBitmap () para baixar a imagem. Não funciona.

Precisamos usar BitmapImageViewTarget

Glide.with(this) .load(imageURL)
 .asBitmap()
 .placeholder(R.drawable.bg)
 .into(new BitmapImageViewTarget(imageView) {
            @Override
            public void onResourceReady(Bitmap  drawable, GlideAnimation anim) {
                super.onResourceReady(drawable, anim);
                progressBar.setVisibility(View.GONE);
            }
        });
Pratap
fonte
Veja meu comentário: stackoverflow.com/questions/26054420/… . Essa resposta é uma boa demonstração do que eu disse lá.
TWiStErRob
7

GlideDrawable estão obsoletos, use Drawable simples

RequestOptions requestOptions = new RequestOptions();
requestOptions.placeholder(R.drawable.placeholder);
requestOptions.error(R.drawable.error);

Glide.with(getContext())
                 .setDefaultRequestOptions(requestOptions)
                 .load(finalPathOrUrl)
                 .listener(new RequestListener<Drawable>() {
                        @Override
                        public boolean onLoadFailed(@Nullable GlideException e, Object model, Target<Drawable> target, boolean isFirstResource) {
                            progressBar.setVisibility(View.GONE);
                            return false;
                        }

                        @Override
                        public boolean onResourceReady(Drawable resource, Object model, Target<Drawable> target, DataSource dataSource, boolean isFirstResource) {
                            progressBar.setVisibility(View.GONE);
                            return false;
                        }
                    })
                 .into(mImageView);
Alex
fonte
4

Em Kotlin você pode fazer o seguinte

Glide.with(context)
            .setDefaultRequestOptions(RequestOptions().placeholder(R.drawable.ic_image_placeholder).error(R.drawable.ic_image_placeholder))
            .load(url)
            .listener(object : RequestListener<Drawable>{
                override fun onLoadFailed(e: GlideException?, model: Any?, target: Target<Drawable>?, isFirstResource: Boolean): Boolean {
                    return false
                }

                override fun onResourceReady(resource: Drawable?, model: Any?, target: Target<Drawable>?, dataSource: DataSource?, isFirstResource: Boolean): Boolean {
                    return false
                }

            })
            .into(imageView)
Android Dev
fonte
2
  1. Em xml, pegue a barra de progresso com altura e largura (match_parent).
  2. Antes de chamar o método de menção abaixo, defina a visibilidade da barra de progresso como Visível.

    public void setImageWIthProgressBar(Context context, final ImageView imageView, String imageUrl, final ProgressBar progressBar) {
    
            Glide.with(context)
                    .load(imageUrl)
                    .listener(new RequestListener<String, GlideDrawable>() {
                        @Override
                        public boolean onException(Exception e, String model, Target<GlideDrawable> target, boolean isFirstResource) {
                            progressBar.setVisibility(View.GONE);
                            return false;
                        }
    
                        @Override
                        public boolean onResourceReady(GlideDrawable resource, String model, Target<GlideDrawable> target, boolean isFromMemoryCache, boolean isFirstResource) {
                            progressBar.setVisibility(View.GONE);
                            return false;
                        }
                    })
                    .into(imageView);
    
        }//setImageWIthProgressBar
    
Vijesh Jat
fonte
Qual é a diferença entre sua resposta e stackoverflow.com/a/31675796/3812404 ? Além disso, o ponto 1 não é necessário.
HariRam
2

Atualizar:

Glide.with(this)
            .load(imageUrl)
            .listener(new RequestListener<Drawable>() {
                @Override
                public boolean onLoadFailed(@Nullable final GlideException e,
                                            final Object model, final Target<Drawable> target,
                                            final boolean isFirstResource) {
                    showProgress(false);

                    mNoContentTextView.setVisibility(View.VISIBLE);

                    return false;
                }

                @Override
                public boolean onResourceReady(final Drawable resource, 
                                               final Object model, 
                                               final Target<Drawable> target, 
                                               final DataSource dataSource, 
                                               final boolean isFirstResource) {
                    showProgress(false);

                    mNoContentTextView.setVisibility(View.GONE);
                    mContentImageView.setImageDrawable(resource);

                    return false;
                }
            })
            .into(mContentImageView);
Narek Hayrapetyan
fonte
Digamos, se você já tem onResourceReady, qual é a utilidade de "em"? Não posso usar o ouvinte sozinho? Em caso afirmativo, como posso fazer com que ele comece a carregar sem "no?
desenvolvedor Android de
Desenvolvedor @android como eu sei que você pode usar sem entrar
Narek Hayrapetyan
está para tentar
Narek Hayrapetyan
Mas se eu não usar "into", acho que avisa sobre isso.
desenvolvedor Android de
1

Como eu fiz as coisas. o caminho mais curto, código mais limpo

exemplo:

progress_bar.visibility = View.VISIBLE

profilePicturePath?.let {
    GlideApp.with(applicationContext)
        .load(CloudStorage.pathToReference(it))
        .placeholder(R.drawable.placeholder)
        .listener(GlideImpl.OnCompleted {
            progress_bar.visibility = View.GONE
        })
    .into(profile_picture)
} ?: profile_picture.setImageResource(R.drawable.placeholder)

uso:

GlideImpl.OnCompleted {
    // completed
}

basta passar GlideImpl.OnCompleted { }para o Glide's.listener()

Classe GlideImpl.kt que aceita RequestListener do Glide

import android.graphics.drawable.Drawable
import com.bumptech.glide.load.DataSource
import com.bumptech.glide.load.engine.GlideException
import com.bumptech.glide.request.RequestListener
import com.bumptech.glide.request.target.Target

object GlideImpl {

    object OnCompleted : RequestListener<Drawable> {

        private lateinit var onComplete: () -> Unit

        operator fun invoke(onComplete: () -> Unit): OnCompleted {
            OnCompleted.onComplete = { onComplete() }
            return this
        }

        override fun onResourceReady(
            resource: Drawable?,
            model: Any?,
            target: Target<Drawable>?,
            dataSource: DataSource?,
            isFirstResource: Boolean
        ): Boolean {
            onComplete()
            return false
        }

        override fun onLoadFailed(
            e: GlideException?,
            model: Any?,
            target: Target<Drawable>?,
            isFirstResource: Boolean
        ): Boolean {
            onComplete()
            return false
        }
    }
}

e é isso!

Dennis Gonzales
fonte
0

Maneira Kotlin

Glide.with(context)
                .load(image_url)
                .listener(object : com.bumptech.glide.request.RequestListener<Drawable> {
                    override fun onLoadFailed(
                        e: GlideException?,
                        model: Any?,
                        target: Target<Drawable>?,
                        isFirstResource: Boolean
                    ): Boolean {
                        return false
                    }

                    override fun onResourceReady(
                        resource: Drawable?,
                        model: Any?,
                        target: Target<Drawable>?,
                        dataSource: DataSource?,
                        isFirstResource: Boolean
                    ): Boolean {
                        img_product_banner.visibility = View.VISIBLE
                        return false
                    }

                }).placeholder(R.drawable.placeholder)
                .diskCacheStrategy(DiskCacheStrategy.ALL)
                .into(img_product_banner)
Aditya Patil
fonte
-1

Esta é a melhor resposta, pois não usa nenhum hack como definir a visibilidade para obter a saída desejada.

Baixe um gif da barra de progresso, chame-o progressbargife coloque-o na pasta drawable.

        Glide.with(ctx)
            .load(url)
            .thumbnail(Glide.with(ctx).load(R.drawable.progressbargif))
            .diskCacheStrategy(DiskCacheStrategy.SOURCE)
            .error(R.drawable.image_unavailable)
            .crossFade(200)
            .into(iv);

Assim que a imagem do url é carregada, a miniatura desaparece. A miniatura desaparece imediatamente quando a imagem em cache é carregada.

Suku
fonte
4
Acho que foi porque não está respondendo à pergunta: OP já tem um spinner com o qual está satisfeito. Também vai contra as práticas recomendadas do Android: usar GIF como spinner é tão antigo e aumenta o tamanho do APK significativamente; e colocar um GIF em já drawableé ruim porque não é carregado pelo framework, deveria estar dentro rawou, assetsna melhor das hipóteses. Não há nada de errado em alterar a visibilidade quando eventos acontecem em seu aplicativo, o Android foi projetado para isso.
TWiStErRob
1
O usuário também verá um espaço vazio enquanto ocorre a decodificação do GIF, é assíncrona e não imediata. Você também está RESULTarmazenando em cache a barra de progresso, o que significa que vai demorar um pouco para carregar. Os GIFs devem ser SOURCEarmazenados em cache, na melhor das hipóteses, para maior eficiência; mas como se trata de um arquivo local, o cache precisa ser NONEpara não duplicá-lo no disco, consumindo ainda mais espaço do usuário.
TWiStErRob