Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Lazy Loading in ListView with Image. (Cursor Adapter)

Tags:

android

I have a list view which displays videos with their thumbnail image, I am using cursor adapter(Fetches using ContentProvider). Problem is as number of list item increases list view performance becoming very poor. Please let me know best way to make it lazy loading.

New : Finaly I got some solution. Its working fine for me. Please let me know if you have any advice. My new code is here. (It uses stack with Producer Consumer patern and bacground thread for proccesing)

@Override public void bindView(View view, Context context, Cursor cursor) {

    ViewHolder holder = (ViewHolder) view.getTag();
    String name = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Video.Media.TITLE));
    int id = cursor.getInt(cursor.getColumnIndexOrThrow(MediaStore.Video.Media._ID));
    holder.getIdView().setText(name);
    holder.getThumbView().setTag((Integer)id);
    if(LazyLoader.getInstance().containsKey(id)) {
        Object bitmap = LazyLoader.getInstance().getBitMap(id);
        if(null != bitmap && (bitmap instanceof  Bitmap)) {
            holder.getThumbView().setImageBitmap((Bitmap)bitmap);
        } else {
            holder.getThumbView().setImageDrawable(null);
        }
    } else {
        holder.getThumbView().setImageDrawable(null);
        LazyItem lazyItem = new LazyItem();
        lazyItem.setId(id);
        lazyItem.setThumbNail(holder.getThumbView());
        LazyLoader.getInstance().putItem(lazyItem);
    }
}




public class LazyLoaderHelper extends Thread {

    private ContentResolver resolver = null;
    private Activity activity;
    private boolean isActive = true;
    ExecutorService executor;


    public LazyLoaderHelper(Activity _activity , ContentResolver _resolver) {
        resolver = _resolver;
        activity = _activity;
        isActive = true;
        executor = Executors.newFixedThreadPool(10);
    }

    public void stopThread() {
        isActive = false;
        executor.shutdown();
    }

    @Override
    public void run() {
        while (isActive) {
            if(LazyLoader.getInstance().getSize() > 0) {
                final  LazyItem lazyItem = LazyLoader.getInstance().getItem();
                if(null != lazyItem) {

                    executor.execute(new Runnable() {
                        @Override
                        public void run() {

                            BitmapFactory.Options options = new BitmapFactory.Options();
                            options.inSampleSize = 1;

                            if ((null != resolver) && (null != activity)) {
                                final Bitmap thumb = MediaStore.Video.Thumbnails.getThumbnail(resolver, lazyItem.getId(), MediaStore.Video.Thumbnails.MICRO_KIND, options);
                                if (null != thumb) {
                                    LazyLoader.getInstance().putBitMap(lazyItem.getId(), thumb);
                                } else {
                                    LazyLoader.getInstance().putBitMap(lazyItem.getId(), new Object());
                                }

                                if ((Integer) lazyItem.getThumbNail().getTag() == lazyItem.getId()) {
                                    activity.runOnUiThread(new Runnable() {
                                        @Override
                                        public void run() {
                                            if (null != thumb) {
                                                lazyItem.getThumbNail().setImageBitmap(thumb);
                                            } else {
                                                lazyItem.getThumbNail().setImageDrawable(null);
                                            }
                                        }
                                    });
                                }
                            }
                        }
                    });
                }
            }

        }
    }
}
like image 333
Adarsh Gowda Avatar asked Jul 22 '15 09:07

Adarsh Gowda


5 Answers

You can use picaso library for android it is open source and can easily integrate with in your application you can download the library from github from below link

http://square.github.io/picasso/

and can easily implement lazy loading by using following methods in your list view adapter

Picasso supports both download and error placeholders as optional features.

Picasso.with(context) .load(url) .placeholder(R.drawable.user_placeholder) .error(R.drawable.user_placeholder_error) .into(imageView);

Resources, assets, files, content providers are all supported as image sources.

Picasso.with(context).load(R.drawable.landing_screen).into(imageView1); Picasso.with(context).load("file:///android_asset/DvpvklR.png").into(imageView2); Picasso.with(context).load(new File(...)).into(imageView3);

like image 128
kuljeet singh Avatar answered Nov 20 '22 15:11

kuljeet singh


Various libraries are available for lazy loading of image. Picasso & Glide are very good. Integration is also very easy. You can use Picasso if image quality is most important. Use glide for faster loading. Though you can prefer anyone, I recommend to use Glide.

For swapped images there may be a problem in async loading of images. How do you know about thread completion. Any thread can load image anytime.

Thanks

like image 24
Vivek Sinha Avatar answered Nov 20 '22 16:11

Vivek Sinha


  • I'm using the aQuery library for lazy loading of the bitmaps (it also supports http). It is very simple and easy to integrate with the existing code with out making lots of changes.
  • Keep the layout of the items as simple as possible.
  • Make sure you implement the recycling and the and View Holder pattern correctly.

More information about smooth list scrolling is here

like image 2
Georgy Avatar answered Nov 20 '22 15:11

Georgy


In my opinion, you should try the UIL (Universal Image Loader) That lib can display video thumbnails as well as image thumbnails.

Edit: Add imageLoader.displayImage(String uri, ImageView imgView, DisplayImageOptions options); to your getView of your custom adapter

String uri can be file:///mnt/sdcard/video.mp4 // from SD card (video thumbnail)

Hope this help! If you have any issues, please comment below

like image 2
Banana droid Avatar answered Nov 20 '22 15:11

Banana droid


I recommend you to combine the ViewHolder pattern with the library called Picasso.

When loading the image, picasso looks like:

public static class ViewHolder {
    ...
    public ImageView imageView;
}

@Override
    public void bindView(View view, Context context, Cursor cursor) {
    ...
    String thumbnailURL = "image_url_from_cursor";
    Picasso.with(context).load(thumbnailURL)
                                    .placeholder(R.drawable.ic_default_img)
                                    .error(R.drawable.ic_default_img)
                                    .into(holder.imageView);
    ...

Hope it helps.

like image 2
Oscar Salguero Avatar answered Nov 20 '22 16:11

Oscar Salguero