Android 从适配器内部处理多个getView调用的最佳方法

Android 从适配器内部处理多个getView调用的最佳方法,android,listview,Android,Listview,我有一个带有自定义阵列适配器的列表视图。此列表视图中的每一行都有一个图标和一些文本。这些图标在后台下载,缓存,然后使用回调,替换为各自的imageview。每次运行getView()时,都会触发从缓存或下载中获取缩略图的逻辑 现在,根据Romain Guy的说法: “这绝对不能保证 getView()的显示顺序 也不知道打了多少次。” 我看到过这种情况,因为一行大小为2的getView()被调用了六次 如何更改代码以避免重复的缩略图获取请求,并处理视图回收 谢谢。来自api public abs

我有一个带有自定义
阵列适配器的
列表视图
。此
列表视图中的每一行都有一个图标和一些文本。这些图标在后台下载,缓存,然后使用回调,替换为各自的
imageview
。每次运行
getView
()时,都会触发从缓存或下载中获取缩略图的逻辑

现在,根据Romain Guy的说法:

“这绝对不能保证 getView()的显示顺序 也不知道打了多少次。”

我看到过这种情况,因为一行大小为2的getView()被调用了六次

如何更改代码以避免重复的缩略图获取请求,并处理视图回收

谢谢。

来自api

public abstract View   getView  (int position, View  convertView, 
                                 ViewGroup  parent)
convertView—如果可能,要重用的旧视图。注意:在使用之前,您应该检查此视图是否为非null且类型是否合适。如果无法转换此视图以显示正确的数据,此方法可以创建新视图

因此,如果已经为此特定索引调用了getView,那么convertView将是第一次调用返回的视图对象

你可以这样做

if(!(convertView instanceof ImageView)){
   convertView = new ImageView();
   //get image from whereever
} else {} // ImageView already created

最好是创建一个带有缩略图(位图)和文本的对象。如果缩略图在对象中不可用,则读取缩略图。

在适配器中创建ImageView对象数组,并在检索时缓存它们(无论是从缓存还是从web)。例如,在getView中,在获取ImageView之前,请检查它是否已经在本地数组中,如果已经在本地数组中,请使用它,如果没有获取,则在收到后将其存储在本地ImageView数组中以备将来使用

确切地说,当你

android:layout_height="wrap_content"

列表视图中
定义。将其更改为“填充父对象/匹配父对象”将避免此问题。

我也遇到了同样的问题,我更改了listView的布局高度以匹配父对象以解决我的问题。

我的理解是,您需要在此处使用ViewHolder设计模式。仅使用返回的convertView可能会导致重用以前的视图(在本例中分配了其他一些图像)

公共类ImageAdapter扩展了ArrayAdapter{
//图像适配器代码在这里。
私人观众{
公共影像视图;
公共字符串url;
}
@凌驾
公共视图getView(最终整数位置、视图转换视图、视图组父视图){
视图=空;
持票人持票人;
字符串url=getUrl(位置);
if(convertView==null){
//没有要回收的视图。请创建新视图。
视图=充气机。充气(R.layout.image\u布局,父级,false);
viewHolder=新的viewHolder();
viewHolder.imageView=(imageView)view.findViewById(R.id.image\u视图);
viewHolder.url=url;
view.setTag(viewHolder);
}否则{
//我们看到了一个可以循环利用的景观。
视图=转换视图;
viewHolder=((viewHolder)view.getTag());
if(viewHolder.url.equals(url)){
//没事可做,我们已经有了正确信息的视图。
返回视图;
}
}
//请务必设置您的imageView,该视图可由viewHolder.imageView访问
返回视图;
}
}

My Fragment.xml有一个ListView,此ListView的布局设置是android:layout\u height=“wrap\u content”,此ListView稍后将绑定到SimpleCorsorAdapter。那么我在ViewBinder中也遇到了同样的问题,可能会被调用3次。将布局\u height=“wrap\u content”更改为“95p”后,问题得到解决。我确实认为,“包装内容”的高度引起了这个问题。
尝试修改Fragment.xml,我想3次调用问题将不再存在。

它不会完全消除冗余调用问题;但它有助于更好地测量ListView的高度。如果高度测量正确,ListView可以正确确定当前可见的行数,从而减少冗余getView()调用的数量。这对我很有帮助,即使使用水平和水平ListView,更改宽度而不是高度。这是我的答案…非常感谢节省的时间,如果我在每次加载图像、我的“我得到”和空列表之前都写下这篇文章
public class ImageAdapter extends ArrayAdapter<String> {

  // Image adapter code goes here.

  private ViewHolder {
    public ImageView imageView;
    public String url;
  }

  @Override
  public View getView(final int position, View convertView, ViewGroup parent) {
    View view = null;
    ViewHolder viewHolder;
    String url = getUrl(position);
    if (convertView == null) {
      // There was no view to recycle. Create a new view.
      view = inflator.inflate(R.layout.image_layout, parent, false);
      viewHolder = new ViewHolder();
      viewHolder.imageView = (ImageView) view.findViewById(R.id.image_view);
      viewHolder.url = url;
      view.setTag(viewHolder);
    } else {
      // We got a view that can be recycled.
        view = convertView;
        viewHolder = ((ViewHolder) view.getTag());
        if (viewHolder.url.equals(url)) {
          // Nothing to do, we have the view with the correct info already.
          return view;
        }
    }

    // Do work to set your imageView which can be accessed by viewHolder.imageView

    return view;
  }
}