【问题标题】:Scrolling through ListView with some images very laggy在 ListView 中滚动一些图像非常滞后
【发布时间】:2010-09-06 12:21:41
【问题描述】:

我有下面的屏幕,其中包含一些图像(每个可见页面 6 个)。上下滚动对我来说似乎很滞后。就像它再次渲染图像一样。向上滚动似乎比向下滚动更糟糕。

有人知道如何提高此类区域的性能以创建漂亮的平滑滚动吗?

更新:图片和文字都是从我的 SQLite 数据库中检索出来的。该列表是使用 SimpleCursorAdapter 创建的。

private class HistoryViewBinder implements SimpleCursorAdapter.ViewBinder 
{
    //private int wallpaperNumberIndex;
    private int timeIndex;
    private int categoryIndex;
    private int imageIndex;

    private java.text.DateFormat dateFormat;
    private java.text.DateFormat timeFormat;
    private Date d = new Date();

    public HistoryViewBinder(Context context, Cursor cursor) 
    {
        dateFormat = android.text.format.DateFormat.getDateFormat(context);
        timeFormat = android.text.format.DateFormat.getTimeFormat(context);

        //wallpaperNumberIndex = cursor.getColumnIndexOrThrow(HistoryDatabase.KEY_WALLPAPER_NUMBER);
        timeIndex = cursor.getColumnIndexOrThrow(HistoryDatabase.KEY_TIME);
        categoryIndex = cursor.getColumnIndexOrThrow(HistoryDatabase.KEY_CATEGORY);
        imageIndex = cursor.getColumnIndexOrThrow(HistoryDatabase.KEY_IMAGE);
    }

    @Override
    public boolean setViewValue(View view, Cursor cursor, int columnIndex) 
    {
        Log.d(TAG, "setViewValue");

        if (view instanceof TextView)
        {
            Log.d(TAG, "TextView");
            TextView tv = (TextView) view;

            if (columnIndex == timeIndex)
            {
                Log.d(TAG, "timeIndex");
                d.setTime(cursor.getLong(columnIndex));
                tv.setText(timeFormat.format(d) + "  " + dateFormat.format(d));
                return true;
            }
            else if (columnIndex == categoryIndex)
            {
                Log.d(TAG, "categoryIndex");
                tv.setText(cursor.getString(columnIndex));
                return true;
            }
        }
        else if (view instanceof ImageView)
        {
            Log.d(TAG, "ImageView");
            ImageView iv = (ImageView) view;

            if (columnIndex == imageIndex)
            {
                Log.d(TAG, "imageIndex");
                byte[] image = cursor.getBlob(columnIndex);
                Bitmap bitmapImage = BitmapFactory.decodeByteArray(image, 0, image.length);
                iv.setImageBitmap(bitmapImage);
                return true;
            }
        }

        return false;
    }
}

【问题讨论】:

  • 如果您能发布创建单个列表项的 getView 方法的代码,我会很有帮助。
  • @Janusz 我不使用 getView。我使用 SimpleCursorAdapter 创建这个视图。
  • 您能否发布 SimpleCursorAdapter 的创建,如果您正在扩展光标适配器的 bindView 方法?
  • @Janusz 我已经发布了 SimpleCursorAdapter 类。

标签: android performance android-listview


【解决方案1】:

问题是每个图像在视图准备显示的那一刻被解码。 ListView 将回收您的视图,这意味着在视图离开屏幕的那一刻,它将被重用,因此图像将被覆盖并被垃圾收集。如果项目重新进入屏幕,则必须再次从数据库中解码图像。

解码速度相当快,但如果用户很快改变列表中的位置,所有解码调用都会使您的列表非常滞后。

我会实现类似 ImageCache 的东西。一个将带有WeakReferences 的地图保存到图像的类。每次要显示图像时,请查看图像是否已在地图中,并且 WeakReference 是否仍指向对象,如果不是这种情况,则需要对图像进行解码,然后将其存储在地图中。

看看延迟加载问题,这些将向您展示如何将解码置于后台任务中,然后在加载图像时更新列表。这是一个多一点的努力,但它可以使列表更快。如果您打算使用延迟加载问题中的代码示例,请尝试使用 AsyncTasks 而不是 Threads 进行解码。

【讨论】:

  • 你是对的。每次我向上滚动到视图中时,它都会从数据库中检索图像,对其进行解码并显示它。你有没有使用 AsyncTasks 而不是 Threads 进行解码的例子?
【解决方案2】:

这是您应该阅读的内容,它应该可以帮助您解决问题(整个高效显示位图部分): http://developer.android.com/training/displaying-bitmaps/process-bitmap.html

【讨论】:

    【解决方案3】:

    如果您的图片尺寸不合适,它们会被即时缩放,这不是一个便宜的操作,尤其是对于大图片。确保从数据库中加载缩略图,而不是壁纸。

    此外,您可以使用Traceview 了解您的时间都花在了哪里。

    【讨论】:

    • 我使用的是缩略图,但不是您在此处看到的确切尺寸......所以它们确实被缩小了。您认为存储仅用于列表的第二个更小的缩略图会更好吗?单击列表项后,我会使用原始缩略图在其中显示一个 AlertDialog(因此我需要更大的缩略图)。
    • @mlevit:值得一试,或者使用 Traceview 看看您的时间是否似乎花在了调整代码大小上。也可以想象,从 SQLite 中加载 blob 异常缓慢——我从未将图像存储在表中,因此不知道性能特征。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-02-22
    • 1970-01-01
    • 2019-03-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多