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);
}
}
});
}
}
}
});
}
}
}
}
}
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);
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
More information about smooth list scrolling is here
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
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With