androidperformanceimage-loadingvideo-thumbnailsaquery

Load Btimap of Video thumbnails from sdcard


I am developing a module in which I need to show all the video from phone in form of video thumbnails. I have taken BaseAdapter to show all video thumbnails into GridView. The only problem is that I had to write the code extract thumbnail from video file to bitmap in getView() of BaseAdapter.

 ((Activity) context).runOnUiThread(new Runnable() {
            @Override
            public void run() {
                 Bitmap bmThumbnail = ThumbnailUtils.createVideoThumbnail(
                                                videoValues.get(position).getFile()
                                               .getAbsolutePath(), Thumbnails.MINI_KIND);
                 imageThumbnail.setImageBitmap(bmThumbnail);
                 bmThumbnail = null;
    }
    });

I want to load this Asynchronously with some image loader. I have already tried Aquery, Universal Image Loader, Picasso etc but none of them gives asynchronous image loading with memory caching, file caching, failure callback mechanism etc.

Can anyone suggest how can I achieve this efficiently? TIA.


Solution

  • To resolve this issue, I have made a class VideoThumbLoader. It asynchronously generated Bitmap and passes it to adapter. So that main benefit is that the whole process is being handled in background thread.

    The code for class is as below:

    import android.annotation.SuppressLint;
    import android.graphics.Bitmap;
    import android.media.ThumbnailUtils;
    import android.os.AsyncTask;
    import android.provider.MediaStore;
    import android.support.v4.util.LruCache;
    import android.widget.ImageView;
    
    public class VideoThumbLoader {
    
        private LruCache<String, Bitmap> lruCache;
    
        @SuppressLint("NewApi")
        public VideoThumbLoader() {
            int maxMemory = (int) Runtime.getRuntime().maxMemory();// obtain maximum
                                                                    // memory to run
            int maxSize = maxMemory / 4;// get cache memory size 35
            lruCache = new LruCache<String, Bitmap>(maxSize) {
                @Override
                protected int sizeOf(String key, Bitmap value) {
                    // this will be called when the cache deposited in each
                    return value.getByteCount();
                }
            };
        }
    
        public void addVideoThumbToCache(String path, Bitmap bitmap) {
            if (getVideoThumbToCache(path) == null && bitmap != null) {
    
                lruCache.put(path, bitmap);
            }
        }
    
        public Bitmap getVideoThumbToCache(String path) {
    
            return lruCache.get(path);
        }
    
        public void showThumbByAsynctack(String path, ImageView imgview) {
    
            if (getVideoThumbToCache(path) == null) {
                // asynchronous loading
                new MyBobAsynctack(imgview, path).execute(path);
            } else {
                imgview.setImageBitmap(getVideoThumbToCache(path));
            }
        }
    
        class MyBobAsynctack extends AsyncTask<String, Void, Bitmap> {
            private ImageView imgView;
            private String path;
    
            public MyBobAsynctack(ImageView imageView, String path) {
                this.imgView = imageView;
                this.path = path;
            }
    
            @Override
            protected Bitmap doInBackground(String... params) {
    
                Bitmap bitmap = ThumbnailUtils.createVideoThumbnail(params[0],
                        MediaStore.Video.Thumbnails.MINI_KIND);
    
                // provide
                if (getVideoThumbToCache(params[0]) == null) {
                    addVideoThumbToCache(path, bitmap);
                }
                return bitmap;
            }
    
            @Override
            protected void onPostExecute(Bitmap bitmap) {
                if (imgView.getTag().equals(path)) {// through Tag can be bound
                                                    // pictures address and
                                                    // imageView, this address
                                                    // Listview loading the image
                                                    // dislocation solution
                    imgView.setImageBitmap(bitmap);
                }
            }
        }
    }
    

    And from adapter side, simply call:

    private VideoThumbLoader mVideoThumbLoader = new VideoThumbLoader();
     imageThumbnail.setTag(videoValues.get(position).getFile()
                        .getAbsolutePath());// binding imageview
     imageThumbnail.setImageResource(R.drawable.videothumb); //default image
     mVideoThumbLoader.showThumbByAsynctack(videoValues.get(position)
                        .getFile().getAbsolutePath(), imageThumbnail);
    

    P.S: One important thing I had taken a note of was, due to asynchronous downloading of bitmap, there were few cases where thumbnails tend to mix up. So I have tagged the imageview with file path. This way I will have the exact thumbnail for the image.