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?


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ê.


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)

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.


.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);

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);
            }
        });

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);

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)

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
    

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);

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!


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)

-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.


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
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.