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.