【问题标题】:Best way to handle multiple getView calls from inside an Adapter从适配器内部处理多个 getView 调用的最佳方法
【发布时间】:2010-05-20 10:52:25
【问题描述】:

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

现在,根据 Romain Guy 的说法:

"绝对不能保证 getView() 的顺序 也没有调用多少次。”

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

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

谢谢。

【问题讨论】:

    标签: android listview


    【解决方案1】:

    没错,这可能会发生,例如当你有

    android:layout_height="wrap_content"
    

    在您的 ListView 定义中。将其更改为 fill_parent/match_parent 将避免它。

    【讨论】:

    • 并没有完全驱逐冗余调用问题;但它有助于更​​好地测量 ListView 的高度。如果高度测量正确,ListView 可以正确确定当前可见的行数,这可以减少冗余 getView() 调用的数量。
    • 这对我有帮助,即使是水平 ListView,也可以改变宽度而不是高度。
    • 这就是我的答案...非常感谢您节省的时间
    【解决方案2】:

    来自 api。

    public abstract View   getView  (int position, View  convertView, 
                                     ViewGroup  parent)
    

    convertView - 如果可能的话,要重用的旧视图。注意:您应该在使用前检查此视图是否为非空且类型合适。如果无法将此视图转换为显示正确的数据,则此方法可以创建一个新视图。

    因此,如果已针对此特定索引调用 getView,则 convertView 将是从第一次调用返回的 View 对象。

    你可以做类似的事情。

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

    【讨论】:

    • 我如果在每次图像加载之前都写这个,我会得到并清空列表
    【解决方案3】:

    我遇到了同样的问题,我将 listView 的 layout_height 更改为 match_parent 解决了我的问题。

    【讨论】:

      【解决方案4】:

      我的理解是这里需要用到ViewHolder设计模式。仅使用返回的 convertView 可能会导致重用以前的视图(在这种情况下分配了一些其他图像)。

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

      【讨论】:

        【解决方案5】:

        最好用缩略图(位图)和文本创建一个对象。如果缩略图在对象中不可用,请阅读缩略图。

        【讨论】:

          【解决方案6】:

          在您的适配器中创建一个 ImageView 对象数组,并在您检索它们时缓存它们(无论是来自缓存还是 Web)。例如,在 getView 中,在您获取 ImageView 之前,请检查它是否已经在您的本地数组中,如果是,则使用它,如果不获取,则一旦收到存储在本地 ImageView 数组中以供将来使用。

          【讨论】:

            【解决方案7】:

            我的Fragment.xml有一个ListView,这个ListView的布局设置是android:layout_height="wrap_content",这个ListView后面会绑定SimpleCursorAdapter。然后我在 ViewBinder 中遇到了同样的问题,被调用了 3 次。将 layout_height="wrap_content" 更改为 "95p" 后问题解决。我确实认为“wrap_content”高度会导致这个问题。 尝试修改您的 Fragment.xml,我猜 3 次调用的问题将不再存在。

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2013-04-26
              相关资源
              最近更新 更多