20

我包含的每个项目都ListView包含一个ImageView和一个TextView,这将填充远程信息。

我得到了 的 URL ImageView,因此我启动了一个AsyncTask下载图像并setImageBitmap使用下载的位图调用的 URL。

这很顺利,但是在创建 ListView 时,getView()经常调用它。它调用前 10 行的大约 7 次getView(只有 7 行可见)。(所以:0、1 等,10、0、1 等)。

然后我可以顺利滚动到第 10 项。但在那之后,对于每个新行,listview 再次调用getView前 10 个项目的大约 7 倍。(这会导致滞后..)

但是当我从 中删除 时setImageBitmapAsyncTask这一切都不会发生!

可能是什么问题呢?会不会是某些布局太大而导致另一条 getViews ?

这里有一些代码:

<ListView
    android:id="@+id/mylist"
    android:layout_width="wrap_content"
    android:layout_height="fill_parent"
    android:layout_alignParentBottom="true"
    android:layout_below="@+id/mydivider"
    android:divider="@+color/mycolor"
    android:dividerHeight="2dp"
    android:fadingEdge="none"
    android:fastScrollEnabled="true"
    android:listSelector="@android:color/transparent"
    android:scrollbars="horizontal"
    android:scrollingCache="false"
    android:smoothScrollbar="false" />

异步任务:

public static class MyTask extends AsyncTask<String, Integer, Bitmap> {
    private LruCache<String, Bitmap> mMap;
    private String mUri;
    private int mPosition;
    private ViewHolder mHolder;

    public MyTask (ViewHolder holder, int position, LruCache<String, Bitmap> map) {
        mMap = map;
        mHolder = holder;
        mPosition = position;
    }

    @Override
    protected Bitmap doInBackground(String... url) {
        mUri = url[0];
        return getBitmapFromURL(mUri);
    }

    @Override
    protected void onPostExecute(Bitmap b) {
        if (b != null) {
            mMap.put(mUri, b);
            if (mPosition == mHolder.position) {
                holder.image.setImageBitmap(b);
            }
        }
    };
}

获取视图()

row = convertView;
ViewHolder holder;
if (row == null) {
    row = vi.inflate(R.layout.mylayout, null);
    holder = new ViewHolder();
    holder.image = (ImageView) row.findViewById(R.id.myimage);
    holder.title = (TextView) row.findViewById(R.id.mytext);
    row.setTag(holder);
} else {
    holder = (ViewHolder) row.getTag();
}

holder.title.setText("text");
holder.image.setImageResource(R.drawable.mydefaulticon);
holder.position = position;
startMyTask(content, holder, position);

更多信息:

当创建一个新视图时,显示的堆栈跟踪显示 getView 被调用ListView.makeAndAddView() 但在 getViews 的无用条纹中它来自ListView.measureHeigthOfChildren()

所以当我设置位图时,布局似乎发生了变化......

4

5 回答 5

33

问题出在 ListView 的布局中。

参数layout_width设置为wrap_content我改fill_parent的时候问题消失了...

于 2012-06-25T10:17:43.860 回答
3

我建议您观看此视频http://www.youtube.com/watch?v=wDBM6wVEO70

基本上android会多次调用getView来计算视图高度和东西,所以你需要在你的异步中实现某种缓存,检查http://code.google.com/p/android-query/如果你不使用身份验证

于 2012-06-25T09:07:24.890 回答
2

问题是您的 ListView 不知道每个项目是什么。初始化时,ListView 将测量其所有子项并根据此信息绘制自身。您对 AsyncTask 所做的是更改列表中项目的大小,而不是让 ListView 再次完全绘制自己。这会导致您的 ListView 行为异常。

解决方案:您应该通过在您的 AsyncTask 的 PostExecute 中使用notifyDataSetChanged()通知适配器来更新您的 ListView 。这将允许 ListView 使用新信息绘制自己。

我希望它有效!

一些有用的链接:

http://thinkandroid.wordpress.com/2012/06/13/lazy-loading-images-from-urls-to-listviews/

ListView 中图像的延迟加载

于 2012-06-25T09:58:00.507 回答
2

我尝试在 ListView 中使用 fill_parent 作为高度,但我无法完美地实现它,但是我如何通过阻止创建 convertViews(如果它已经存在)来尝试它。它在我的方法中运行良好。

        @Override
        public View getView(final int position, View convertView, ViewGroup parent) {
         if (convertView != null)
            return convertView;
         else {
            //your code...
         }
    }
于 2017-07-24T11:59:39.983 回答
0

抱歉回复晚了。我在我的画廊小部件适配器中遇到了同样的问题。我使用了通用图像加载器。Martijn 的解决方案对我有用。我所要做的就是在图像完全下载并设置 imageView 时添加notifyDataSetChanged() 。

于 2013-08-23T10:13:52.670 回答