Reputation: 1548
I'm trying to to show a ListView with goods. Goods is a SQLite table with title, count and image (BLOB). So my ListView is not smooth.
What have I tried:
I went by another way:
ExifInterface
and rotate image if needed.setPic()
method from http://developer.android.com/training/camera/photobasics.html
and save this small thumb to SQLite database Goods table.Now ListView become scrolling hard when number of Goods is over 100. And this is not the problem solution.
So I need some different way to fill ListView with images.
Please, direct me in right way )))
Thanks!
P.S. I'm using custom SimpleCursorAdapter to show data:
public class GoodsCursorAdapter extends SimpleCursorAdapter {
public GoodsCursorAdapter(Context context) {
super(context, R.layout.cell_goods, null,
new String[] { "title", "countAvail" },
new int[] { R.id.lbTitle, R.id.lbCount }, 0);
}
private class ViewHolder {
ImageView imageView;
TextView lbTitle, lbCount;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder viewHolder;
if (convertView == null){
LayoutInflater inflater = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = inflater.inflate(R.layout.cell_goods, parent, false);
viewHolder = new ViewHolder();
viewHolder.imageView = (ImageView) convertView.findViewById(R.id.ivThumb);
viewHolder.lbTitle = (TextView) convertView.findViewById(R.id.lbTitle);
viewHolder.lbCount = (TextView) convertView.findViewById(R.id.lbCount);
convertView.setTag(viewHolder);
} else {
viewHolder = (ViewHolder) convertView.getTag();
}
mainCursor.moveToPosition(position);
byte[] byteArray = mainCursor.getBlob(mainCursor.getColumnIndex("photo"));
if (byteArray != null) {
Bitmap bitmap = BitmapFactory.decodeByteArray(byteArray, 0, byteArray.length);
Log.d("INFO", mainCursor.getString(mainCursor.getColumnIndex("title"))+": "+String.valueOf(bitmap.getWidth())+"x"+String.valueOf(bitmap.getHeight())+"("+String.valueOf(bitmap.getByteCount()/1024)+"Kb)");
viewHolder.imageView.setImageBitmap(bitmap);
} else {
viewHolder.imageView.setImageResource(R.drawable.ic_action_picture);
}
viewHolder.lbTitle.setText(mainCursor.getString(mainCursor.getColumnIndex("title")));
viewHolder.lbCount.setText(String.format(getString(R.string.lbCount), mainCursor.getString(mainCursor.getColumnIndex("countAvail"))));
return convertView;
}
Upvotes: 3
Views: 2558
Reputation: 1548
Ok guys, I have tried almost all methods you suggested. And here is my report:
@HareshChhelana's method is use inSampleSize
option (from BitmapFactory.Options
). Method is better then storing small thumbnail in SQLite (as I have done first), but become not smooth for more then 200 list items with images
@Zain's suggestion to use Google solution (http://developer.android.com/training/displaying-bitmaps/process-bitmap.html). This also works fine.
Pagination from @Prachi. Works fine. But I did not add any logic to load next batch on listview's onscroll. My solution was: fetch first 30 rows and as use "Next 30 rows" and "Prev 30 rows" button. As this method was the last solution for me if no one methods without pagination won't work, I skip it. :)
@Pankaj's suggestion. I walked through this class and it looks like working solution, but I did not try it. Anyway answer is useful.
I have found a library, which I used in my project: https://github.com/nostra13/Android-Universal-Image-Loader It's really great and have a lot of useful settings!
P.S. Sorry for my english :)
Upvotes: 0
Reputation: 2372
Trying loading the images off the UI thread - using an AsyncTask.
Something like this (taken from here)
class BitmapWorkerTask extends AsyncTask<Cursor, Void, Bitmap> {
private final WeakReference<ImageView> imageViewReference;
private Cursor mCursor;;
public BitmapWorkerTask(ImageView imageView) {
// Use a WeakReference to ensure the ImageView can be garbage collected
imageViewReference = new WeakReference<ImageView>(imageView);
}
// Decode image in background.
@Override
protected Bitmap doInBackground(Cursor... params) {
mCursor = params[0];
byte[] byteArray = mCursor.getBlob(mCursor.getColumnIndex("photo"));
if (byteArray != null) {
Bitmap bitmap = BitmapFactory.decodeByteArray(byteArray, 0, byteArray.length);
return bitmap;
}
}
// Once complete, see if ImageView is still around and set bitmap.
@Override
protected void onPostExecute(Bitmap bitmap) {
if (imageViewReference != null && bitmap != null) {
final ImageView imageView = imageViewReference.get();
if (imageView != null) {
imageView.setImageBitmap(bitmap);
}
}
}
}
So modify
if (byteArray != null) {
BitmapWorkerTask task = new BitmapWorkerTask(imageView);
task.execute(mainCursor);
}else{......}
Upvotes: 2
Reputation: 2559
Use pagination ..fetch 5/10 rows and to load bitmaps use Picasso or you can load bitmap in async
EDIT
mListView.setOnScrollListener(new AbsListView.OnScrollListener() {
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
if (scrollState == 1) {
isUserScroll = true;
} else {
isUserScroll = false;
}
}
@Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
if (isUserScroll) {
int lastInScreen = firstVisibleItem + visibleItemCount;
if (!isDataLoading && (lastInScreen == totalItemCount)) {
//load data
isDataLoading = true;
}
}
}
});
Upvotes: 1
Reputation: 861
Use lazy list for downloading image in listview. Ref link: http://www.prandroid.com/2014/07/how-to-lazy-load-of-images-in-listview.html
Upvotes: 1
Reputation: 4530
Load all bitmaps outside getview() either in constructor or rather outside adapter then assign it to adapter. Loading image every time from database when view is created may slow down the scroll.
In case you face any memory issue In preloding Images try caching them on memory instead of saving to database
Upvotes: 0