Đặt khả năng hiển thị của thanh tiến trình khi hoàn thành tải hình ảnh bằng thư viện Glide


90

Xin chào Tôi muốn có một thanh tiến trình cho hình ảnh sẽ hiển thị trong khi tải hình ảnh nhưng khi tải hình ảnh sẽ hoàn tất, tôi muốn đặt nó thành biến mất. Trước đó tôi đã sử dụng thư viện Picasso cho việc này. Nhưng tôi không biết cách sử dụng nó với thư viện Glide. Tôi có ý tưởng rằng một số chức năng sẵn sàng tài nguyên ở đó nhưng tôi không biết cách sử dụng nó. Ai giúp tôi với?

Mã cho Thư viện 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() {
           }
        })
;

Bây giờ Tôi có thể làm điều này bằng Glide bằng cách nào?

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

Tôi có thể tải hình ảnh bằng cách này với Glide nhưng làm thế nào tôi có thể viết progressBar.setVisibility(View.GONE);ở đâu đó trong mã nếu hình ảnh được tải?


2
Tại sao bạn lại thay đổi thư viện của mình? Picasso rất tuyệt.
tasomaniac

Tôi cũng khuyên bạn nên gắn bó với Picasso trừ khi bạn có lý do chính đáng để thay đổi thư viện
Chris

Câu trả lời:


229

Câu hỏi đã khá cũ, và tôi không biết tình huống với lượn vào thời điểm đó là gì, nhưng bây giờ nó có thể dễ dàng thực hiện với người nghe (không phải như đề xuất trong câu trả lời được chọn là đúng).

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

Bạn trả về true nếu muốn tự xử lý những thứ như hoạt ảnh và false nếu muốn lướt để xử lý chúng cho bạn.


13
Hãy xem xét ẩn progressBartrong onExceptionlà tốt, nếu không nó sẽ quay vô thời hạn cho hi vọng sai lầm. Một khi onExceptionđược gọi là Glide sẽ không làm gì khác hơn là thiết lập những gì được chuyển đến .error().
TWiStErRob

2
Điều này có thể dẫn đến một NullPointerException nếu bạn rời khỏi Fragment / Activity trước khi tải hình ảnh.
aProperFox

1
Tôi không kích động bạn tạo ra những người nghe nội tâm, chỉ là cách ngắn gọn nhất để thể hiện một công cụ để hoàn thành nhiệm vụ.
Yaroslav

1
Điều chắc chắn, tôi giải quyết điều này bằng cách thêm một cuộc gọi trong onDestroyVIew () trước khi cuộc gọi siêu để nói Glide.clear (yourImageView)
aProperFox

7
LƯU Ý: .listenerphải được gọi trước.into()
Ahmed Mostafa

31

Nếu bạn muốn làm điều này trong KOTLIN, bạn có thể thử theo cách đó:

    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
Cũng cần nhập Mục tiêu:import com.bumptech.glide.request.target.Target
Gibolt

@Gibolt điều này đã làm phiền tôi trong 10 phút liên tiếp
johnrao07

17

Câu trả lời của tôi dựa trên các API lỗi thời. Xem ở đây để có câu trả lời cập nhật hơn.


.listener()sẽ tốt hơn vì bạn sẽ nhận được nhiều thông tin hơn về tải của mình (kiểu máy, bộ nhớ đệm, ...) nên dễ dàng quyết định logic tùy chỉnh hơn. RequestListenercũng ổn định hơn, việc ghi đè Targetsẽ tạo ra sẽ không mang lại cho bạn lợi ích của các bản sửa lỗi trong tương lai. Bạn cũng có thể dễ dàng tạo một mã VisibilityListener<T, R>mà bạn có thể sử dụng lại trong các ngữ cảnh khác nhau.
TWiStErRob

10

Trong trường hợp ngoại lệ, hãy đặt một điều kiện để hiển thị lại 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

Giải pháp trên cũng hoạt động khá tốt đối với tôi nhưng khi tôi sử dụng asBitmap () để tải xuống hình ảnh. Nó không hoạt động.

Chúng tôi cần sử dụng 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);
            }
        });

Xem nhận xét của tôi: stackoverflow.com/questions/26054420/… . Câu trả lời này là một minh chứng tốt cho những gì tôi đã nói ở đó.
TWiStErRob

7

GlideDrawable không được dùng nữa, hãy sử dụng Drawable đơn giản

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

Trong Kotlin, bạn có thể làm như dưới đây

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. Trong xml lấy thanh tiến trình với chiều cao và chiều rộng (match_parent).
  2. Trước khi gọi phương pháp đề cập bên dưới, hãy đặt chế độ hiển thị thanh tiến trình Hiển thị.

    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
    

Câu trả lời của bạn khác với stackoverflow.com/a/31675796/3812404 như thế nào? Ngoài ra, điểm 1 là không cần thiết.
HariRam

2

Cập nhật:

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

Giả sử, nếu bạn đã có onResourceReady, thì việc sử dụng "into" là gì? Tôi không thể chỉ sử dụng trình nghe một mình? Nếu vậy, làm cách nào để tôi có thể bắt đầu tải mà không cần "vào?
nhà phát triển android

Nhà phát triển @android như tôi biết bạn có thể sử dụng mà không cần vào
Narek Hayrapetyan

Nó có thể thử
Narek Hayrapetyan

Nhưng nếu tôi không sử dụng "into", tôi nghĩ nó cảnh báo về điều đó.
nhà phát triển android

1

Tôi đã làm mọi thứ như thế nào. cách ngắn hơn, mã sạch hơn

thí dụ:

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)

sử dụng:

GlideImpl.OnCompleted {
    // completed
}

chỉ cần chuyển GlideImpl.OnCompleted { }đến Glide's.listener()

Lớp GlideImpl.kt chấp nhận RequestListener của 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
        }
    }
}

Và đó là nó!


0

Kotlin cách

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

Đây là câu trả lời tốt nhất vì nó không sử dụng bất kỳ hình thức hack like thiết lập khả năng hiển thị nào để có được đầu ra mong muốn.

Tải xuống một gif của thanh tiến trình và gọi nó progressbargifvà đặt nó vào thư mục có thể vẽ.

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

Sau khi hình ảnh url được tải, hình thu nhỏ sẽ biến mất. Hình thu nhỏ sẽ biến mất ngay lập tức khi tải hình ảnh đã lưu trong bộ nhớ cache.


4
Tôi nghĩ đó là vì nó không trả lời được câu hỏi: OP đã có một con quay mà anh ấy hài lòng. Nó cũng chống lại các phương pháp hay nhất của Android: sử dụng GIF làm spinner đã có từ những năm 90 và tăng kích thước APK đáng kể; và việc đưa GIF vào drawablebản thân nó là không tốt vì nó không được tải bởi khuôn khổ, nó phải ở trong rawhoặc assetstốt nhất. Không có gì sai khi thay đổi chế độ hiển thị khi các sự kiện xảy ra trong ứng dụng của bạn, Android được thiết kế cho điều đó.
TWiStErRob

1
Người dùng cũng sẽ thấy một khoảng trống trong khi quá trình giải mã GIF diễn ra, nó không đồng bộ và không ngay lập tức. Bạn cũng đang RESULTtruy cập thanh tiến trình, có nghĩa là sẽ mất một lúc để tải. GIF nên được SOURCElưu vào bộ nhớ cache tốt nhất để đạt hiệu quả; nhưng vì đây là một tệp cục bộ, bộ nhớ đệm cần phải được NONEsao chép nó trên đĩa, thậm chí còn tiêu tốn nhiều dung lượng người dùng hơn.
TWiStErRob
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.