Android - ListView with scrollable images is not smooth

I am trying to show a ListView with products. Products is a SQLite table with title, quantity and image (BLOB). Therefore my ListView is not smooth.

What I have tried:

  • Open camera intent, capture, get additional functionality and insert into SQLite. So I only used one bitmap. This method worked fine until the number of Products was less than 50.

I went the other way:

Now the ListView scrolls when the number of Products exceeds 100. This is not a problem.

So I need a slightly different way to fill the ListView with images.

Please guide me correctly)))

Thank!

PS I am using a custom SimpleCursorAdapter to display 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;
    }

      

+3


source to share


5 answers


Ok guys, I tried almost all the methods you suggested. And here is my report:

  • @HareshChhelana's method uses the inSampleSize

    (from BitmapFactory.Options

    ) parameter . The method is better and then save a small thumbnail in SQLite (as I did at the beginning), but became not smooth for over 200 list items with images

  • @ Close suggestion to use google solution ( http://developer.android.com/training/displaying-bitmaps/process-bitmap.html ). This also works great.

  • Paging from @ Prachi. Works fine. But I didn't add any logic to load the next batch in the listview onscroll. My solution was: extract the first 30 rows and use the "Next 30 rows" and "Prev 30 rows" buttons. Since this method was the last solution for me, if no one is using no pagination won't work, I'll skip it. :)

  • @ Pankaj's suggestion. I went through this class and it looks like a working solution , but I haven't tried it. The answer is helpful anyway.



I found a library that I used in my project: https://github.com/nostra13/Android-Universal-Image-Loader This is really cool and has a lot of useful settings!

PS Sorry for my english :)

0


source


Trying to load images from the UI thread - using 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 change

 if (byteArray != null) {     
  BitmapWorkerTask task = new BitmapWorkerTask(imageView);
  task.execute(mainCursor);
 }else{......}

      

+2


source


Use a lazy list to load the image into the listview. Link link: http://www.prandroid.com/2014/07/how-to-lazy-load-of-images-in-listview.html

+1


source


Use pagination..fetch 5/10 lines and for loading 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;
                    }
                }
            }
        });

      

+1


source


Load all bitmaps outside of getview () either into the constructor or rather from an external adapter and then assign it to the adapter. Loading an image every time from the database when creating a view can slow down scrolling.

If you are experiencing a memory problem In prelate mode, images try to cache them in memory instead of saving them to the database

0


source







All Articles