2012-06-25 99 views
19

我的ListView中的每个项目都包含一个ImageView和一个TextView,这将填充远程信息。另一个getView被多次调用

我得到了一个URL为ImageView,因此我开始AsyncTask下载图像,并将下载的位图调用setImageBitmap

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

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

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

可能是什么问题?难道这是一些布局是大的,这将导致另一条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); 

一些更多的信息:

当新视图创建堆栈跟踪显示n中的getView从ListView.makeAndAddView() 称为但是在getViews的无用连胜它是从ListView.measureHeigthOfChildren()

所以好像当我设置位图的布局发生变化来了...

+0

是看起来那么即使我认为家长应重新布局时,图像会添加它自身作为父高度也得到由that..But影响,这是我想不知道.. –

回答

32

的问题是在ListView的布局。

参数layout_width设置为wrap_content当我把它改成fill_parent问题就消失了......

+2

感谢您的支持。工作100%。 – Ron

+0

也为我工作。我想知道它是否与listView的内在大小有限,如果它匹配它的父代而不是填充它?更大的listView会更频繁地在逻辑上调用getView(),因为有更多的单个项目可用。 –

+1

在我的情况下,即使这个特定的位置没有特别的东西,getView被重复和无限地调用一个位置。我有多个视图类型,就像在同一个屏幕上以及另一个视图类型一样。问题是我在布局中有多个项目,其中一个项目的宽度由layoutWeight =“1”确定,以便在其他小部件之后占用剩余空间。重新排列这个固定的宽度解决了这个问题。 – velis

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

+0

看看这个链接: http://stackoverflow.com/a/5092426/929075当我只想更新一个视图时,notifyDataSetChanged不起作用。我不会更改ArrayList –

0

对不起,迟到的答复。我在我的图库插件适配器中遇到了同样的问题。我曾经使用过Universal Image Loader。 Martijn的解决方案为我工作。我所要做的只是在图像完全下载并设置了imageView时添加notifyDataSetChanged()

0

我尝试使用fill_parent作为ListView中的高度,但我无法实现它完美,但我怎么试过它通过防止创建convertViews,如果它已经存在。它在我的appoach中工作正常。

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