Imposta la visibilità della barra di avanzamento al completamento del caricamento dell'immagine utilizzando la libreria Glide


90

Salve, desidero avere una barra di avanzamento per l'immagine che verrà mostrata durante il caricamento dell'immagine, ma quando il caricamento dell'immagine sarà completato, voglio impostarlo come sparito. In precedenza stavo usando la libreria Picasso per questo. Ma non so come usarlo con la libreria Glide. Ho idea che ci sia qualche funzione pronta per le risorse ma non so come usarla. Qualcuno può aiutarmi?

Codice per la 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() {
           }
        })
;

Ora come posso farlo con Glide?

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

Sono in grado di caricare l'immagine da questo con Glide, ma come posso scrivere progressBar.setVisibility(View.GONE);da qualche parte nel codice se l'immagine viene caricata?


2
Perché hai cambiato la tua libreria? Picasso è fantastico.
tasomaniac

Consiglierei anche di restare con Picasso a meno che tu non abbia buone ragioni per cambiare le librerie
Chris

Risposte:


229

La domanda è piuttosto vecchia, e non so quale fosse la situazione con il glide a quei tempi, ma ora può essere fatta facilmente con l'ascoltatore (non come proposto nella risposta scelta come corretta).

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

Ritorni vero se vuoi gestire cose come le animazioni da solo e falso se vuoi che glide le gestisca per te.


13
Considerare nascondendo la progressBarin onExceptionpure, altrimenti sarà girare all'infinito dando false speranze. Una volta onExceptionchiamato Glide non farà altro che impostare ciò che viene passato .error().
TWiStErRob

2
Ciò può causare un'eccezione NullPointerException se si lascia il frammento / attività prima del caricamento dell'immagine.
aProperFox

1
Non ti sto spingendo a creare ascoltatori di classe interna, solo il modo più conciso per mostrare uno strumento per portare a termine il compito.
Yaroslav

1
Certo, ho risolto questo problema aggiungendo una chiamata in onDestroyVIew () prima della super chiamata per dire Glide.clear (yourImageView)
aProperFox

7
NOTA: .listenerdeve essere chiamato prima.into()
Ahmed Mostafa

31

Se vuoi farlo in KOTLIN, puoi provare in questo modo:

    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)

5
Inoltre è necessario importare Target:import com.bumptech.glide.request.target.Target
Gibolt

@ Gibolt questo mi ha infastidito per 10 minuti di
fila

17

La mia risposta era basata su API obsolete. Vedi qui per la risposta più aggiornata.


.listener()è meglio perché riceverai più informazioni sul tuo carico (modello, cache di memoria, ...) quindi è più facile decidere una logica più personalizzata. RequestListenerè anche più stabile, ignorare quale Targetcreare non ti darà il vantaggio di correzioni future. Puoi anche creare facilmente un'immagine VisibilityListener<T, R>che puoi riutilizzare in diversi contesti.
TWiStErRob

10

In eccezione metti una condizione per mostrare nuovamente il file 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);

7

La soluzione di cui sopra funziona abbastanza bene anche per me, ma quando uso asBitmap () per scaricare l'immagine. Non funziona.

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

Vedi il mio commento: stackoverflow.com/questions/26054420/… . Questa risposta è una buona dimostrazione di ciò che ho detto lì.
TWiStErRob

7

GlideDrawable sono deprecati, usa il semplice Drawable

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

In Kotlin puoi fare come di seguito

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. In xml prendi la barra di avanzamento con altezza e larghezza (match_parent).
  2. Prima di chiamare il metodo di menzione di seguito, impostare la visibilità della barra di avanzamento Visibile.

    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
    

In che modo la tua risposta è diversa da stackoverflow.com/a/31675796/3812404 ? Inoltre, il punto 1 non è necessario.
HariRam

2

Aggiornare:

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

Dì, se hai già onResourceReady, a cosa serve "into"? Non posso usare l'ascoltatore da solo? In tal caso, come posso avviare il caricamento senza "in?
sviluppatore Android il

@ sviluppatore Android come so che puoi usare senza in
Narek Hayrapetyan

sta per provare
Narek Hayrapetyan il

Ma se non uso "into", penso che lo avverta.
sviluppatore Android

1

Come ho fatto le cose. il modo più breve, codice più pulito

esempio:

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)

utilizzo:

GlideImpl.OnCompleted {
    // completed
}

basta passare GlideImpl.OnCompleted { }al Glide's.listener()

GlideImpl.kt che accetta RequestListener di 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 questo è tutto!


0

Modo 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

Questa è la risposta migliore in quanto non utilizza alcun hack come l'impostazione della visibilità per ottenere l'output desiderato.

Scarica una gif della barra di avanzamento e chiamala progressbargife mettila nella cartella disegnabile.

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

Una volta caricata l'immagine dell'URL, la miniatura scompare. La miniatura scompare immediatamente quando viene caricata l'immagine memorizzata nella cache.


4
Penso che sia stato perché non risponde alla domanda: OP ha già uno spinner di cui è soddisfatto. È anche contro le migliori pratiche di Android: usare GIF come spinner è così anni '90 e aumenta significativamente le dimensioni dell'APK; e mettere una GIF dentro drawableè di per sé un male perché non è caricato dal framework, dovrebbe essere dentro rawo assetsnella migliore delle ipotesi. Non c'è niente di sbagliato nel cambiare la visibilità quando si verificano eventi nella tua app, Android è progettato per questo.
TWiStErRob

1
L'utente vedrà anche uno spazio vuoto mentre avviene la decodifica GIF, è asincrona e non immediata. Stai anche RESULTmemorizzando nella cache la barra di avanzamento, il che significa che ci vorrà un po 'per caricare. Le GIF dovrebbero essere SOURCEmemorizzate nella cache al meglio per l'efficienza; ma poiché si tratta di un file locale, la cache deve essere NONEper non duplicarlo su disco, consumando ancora più spazio utente.
TWiStErRob
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.