Android - 带图像的ListView滚动不流畅

时间:2015-04-22 10:10:36

标签: android image listview

我试图用商品展示ListView。 商品是包含标题,计数和图片(BLOB)的SQLite表。所以我的ListView不顺畅。

我尝试了什么:

  1. 打开相机意图,捕获,获取Extras并插入SQLite。所以我只使用了一个位图。这种方法工作正常,直到货物数量少于50个。
  2. 我走了另一条路:

    1. 打开相机意图,捕获并保存到文件。
    2. 检查ExifInterface并根据需要旋转图像。
    3. 使用http://developer.android.com/training/displaying-bitmaps/load-bitmap.html缩放到300x300大小并移动到我的文件夹。此图像文件用于全屏。
    4. 现在我需要一个缩略图,以便将来将它放入ListView。所以我使用http://developer.android.com/training/camera/photobasics.html中的setPic()方法将文件(3)缩放到缩略图大小(例如60x60) 并将此小拇指保存到SQLite数据库商品表。
    5. 现在,当商品数量超过100时,ListView会变得很难滚动。这不是问题解决方案。

      所以我需要一些不同的方法来用图像填充ListView。

      请以正确的方式指导我)))

      谢谢!

      P.S。我使用自定义SimpleCursorAdapter来显示数据:

      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;
          }
      

5 个答案:

答案 0 :(得分:2)

尝试使用AsyncTask从UI线程加载图像。

这样的事情(取自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);
        }
    }
  }
}

所以修改

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

答案 1 :(得分:1)

使用延迟列表在listview中下载图像。 参考链接:http://www.prandroid.com/2014/07/how-to-lazy-load-of-images-in-listview.html

答案 2 :(得分:1)

使用pagination ..fetch 5/10行并加载位图使用Picasso 或者您可以在异步

中加载位图

修改

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;
                    }
                }
            }
        });

答案 3 :(得分:0)

在构造函数或外部适配器中将所有位图加载到getview()之外,然后将其分配给适配器。在创建视图时每次从数据库加载图像可能会减慢滚动速度。

如果您遇到任何内存问题在预刻录映像中尝试将它们缓存在内存中 而不是保存到数据库

答案 4 :(得分:0)

好吧,伙计们,我几乎尝试了你建议的所有方法。这是我的报告:

  1. @ HareshChhelana的方法是使用inSampleSize选项(来自BitmapFactory.Options)。方法是更好然后在SQLite中存储小缩略图(正如我先做的那样),但是对于带有图像的200多个列表项变得不顺畅

  2. @ Zain建议使用Google解决方案(http://developer.android.com/training/displaying-bitmaps/process-bitmap.html)。 这也可以。

  3. 来自@Prachi的分页。 工作正常。但是我没有添加任何逻辑来加载listview的onscroll上的下一批。我的解决方案是:获取前30行并使用&#34;接下来的30行&#34;和&#34;上一页30行&#34;按钮。因为如果没有一个没有分页的方法没有工作,这个方法对我来说是最后一个解决方案,我跳过它。 :)

  4. @ Pankaj的建议。我走过这个课程并且看起来像是工作解决方案,但我没有尝试过。无论如何,答案很有用。

  5. 我找到了一个我在项目中使用的库: https://github.com/nostra13/Android-Universal-Image-Loader 它真的很棒,并且有很多有用的设置!

    P.S。对不起我的英文:)