另一个getView被多次调用

时间:2012-06-25 08:42:36

标签: android listview

我的ListView中的每个项目都包含ImageViewTextView,这将填充远程信息。

我收到了ImageView的网址,因此我开始AsyncTask下载图片,并使用下载的位图调用setImageBitmap

这很顺利但是当创建ListView时,经常会调用getView()。 对于前10行,它只调用了getView的7倍(只有7行可见)。 (所以:0,1等,10,0,1等)。

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

但是当我从setImageBitmap中移除AsyncTask时,这一切都不会发生!

可能是什么问题?可能是某些布局是大的,这将导致另一连串的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" />

AsyncTask:

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

getView()

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

更多信息:

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

因此,当我设置位图时似乎更改了布局......

5 个答案:

答案 0 :(得分:32)

问题出在ListView的布局中。

当我将参数layout_width更改为wrap_content问题时,参数fill_parent已设置为{{1}} ...

答案 1 :(得分:3)

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

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

答案 2 :(得分: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/

Lazy load of images in ListView

答案 3 :(得分:0)

很抱歉迟到的回复。我在适配器库窗口小部件中遇到了同样的问题。我雇用了Universal Image Loader。 Martijn的解决方案对我有用。我所要做的就是在完全下载图像并设置imageView时添加 notifyDataSetChanged()

答案 4 :(得分:0)

我尝试在ListView中使用fill_parent作为高度,但我无法实现它完美,但我怎么试过它,如果它已经存在则阻止创建convertViews。它在我的任命中运作良好。

        @Override
        public View getView(final int position, View convertView, ViewGroup parent) {
         if (convertView != null)
            return convertView;
         else {
            //your code...
         }
    }