android - GetView() 中的 ConvertView

标签 android android-listview

我正在努力思考 getView(),我认为 Android 中没有任何主题会在 StackOverflow 和其他地方引起更多的困惑和问题。每个人都想知道为什么它被调用了这么多次,以什么顺序调用或者根本不调用,但正如 Romain Guy 所说 here , "绝对不能保证 getView() 的调用顺序和调用次数。"

所以我有一个不同的问题:我不明白convertView 参数。

我有一个包含 15 项的列表,其中 11 项可以显示在屏幕上。我的应用第一次启动 getView() 被调用了 48 次。

convertView 在第一次调用时位置 0 为 null,位置 1-11 为非 null,然后位置 0 为非 null,位置 1-11 为 null,然后位置 0 为 null,位置为 non-null 1-11,最后位置 0-11 非空。

有人可以解释为什么/何时 convertView 为 null 与非 null,对于大多数位置它如何/为什么从非 null 开始,以及为什么相同的位置似乎在这两种状态之间来回反弹?

对用清晰的英语编写的详细解释 convertView 的优秀教程的引用也将不胜感激。

PS - 我的测试是在运行 Android 2.3.5 的设备上完成的,如果这很重要的话。我知道从那时起 Google 已经多次更改 ListActivity/adapter/getView 的内容。

根据请求,我包含了适配器代码(我已经隐藏了一些专有名称)。不幸的是,我无法回答任何“你为什么这样做?”问题,因为不是我写的

protected class PLxxxAdapter extends BaseAdapter {

    public PLxxxAdapter(Context c) {
    }

    @Override
    public int getCount() {
        return listItems.size();
    }

    @Override
    public Object getItem(int position) {
        return listItems.get(position);
    }

    @Override
    public long getItemId(int position) {
        return position;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        ViewHolder holder;
        boolean select;

        if (convertView == null) {              
            LayoutInflater vi = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            convertView = vi.inflate(R.layout.PLxxxitem, null);
            //This is still needed even though we point to an XML description
            convertView.setLayoutParams(new ListView.LayoutParams(
                    ListView.LayoutParams.MATCH_PARENT,
                    ListView.LayoutParams.MATCH_PARENT));
            holder = new ViewHolder();

            //Get the views of the row
            holder.itemView = (TextView)convertView.findViewById(R.id.post);
            holder.cV1 = (CheckedTextView)convertView.findViewById(R.id.check1);

            //Init the 'confirm' box listener
            holder.cV1.setCompoundDrawablesWithIntrinsicBounds(0, R.layout.smallcb, 0, 0);
            holder.cV1.setOnClickListener(new ConfBoxListener());

            convertView.setTag(holder);
            holder.cV1.setTag(holder);  //These views need tags for onClick()
        }
        else {
            holder = (ViewHolder)convertView.getTag();  // convertview NOT null
        }

       try  {
          int liSize = listItems.size();
          if (position < liSize)  {
             holder.itemView.setText(listItems.get(position));
          }
       }
       catch (Exception e)  {
              Log.e ("PLxxxActivity.getView Crash", "details " + e);
       }
        holder.cV1.setChecked(confirmed.get(position));
        select = selected.get(position);

        if (select == true)   {
            convertView.setBackgroundResource(R.color.colBlue);
        }               

        else
            convertView.setBackgroundResource(R.color.colGrey);
        holder.position = position;
        if (RemoteControlActivity.confCBs == true)
            holder.cV1.setVisibility(View.VISIBLE);
        else
            holder.cV1.setVisibility(View.INVISIBLE);

        return convertView;
    }  // end getView
}  //end class PLxxxAdapter

最佳答案

x 次,其中 x 是一个接近屏幕上可见项目数的数字,convertViewnull 。您需要实例化一个新的 View 才能返回。

当您向下滚动时,现有的 View 会被向上推到看不见的地方。它现在可以重新使用,而不是销毁它。您会注意到,就在一个新的 View 从下面被插入之前,您的 getView 方法被调用,带有一个有效的 convertView。这正是之前被推到视线之外的那个 View(或者可能是另一个,有一些额外的逻辑)!

因此,您可以重用View 并使其适应新的item,而不是重新实例化您的View,这是昂贵的它代表。你会经常看到类似的东西:

View view = convertView;
if(view == null){
    view = LayoutInflater.from(getContext()).inflate(...);
}

// 'bind' view

return view;

事实上,您的 getView 方法在启动时被调用了 48 次,这实际上可能是您的代码存在问题。

关于android - GetView() 中的 ConvertView,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23571539/

相关文章:

android - 动态缩放文本以确保它适合单行 TextView

android - 使用 ListView 和按钮限制 LinearLayout 的高度

android - 如何从 JSONArray 创建 Cursor?

Android:Master Detail模板中ListView默认选择第一项

java - 发送带有参数的解析云代码时出现 IllegalArgumentException

android - 密码在一个大块中返回整个文件

android - 使用最新数据动态刷新 RecyclerView

java - 2D渲染颜色问题

android - 从上到下滚动时如何自动停止 ListView 取消选择项目?

android - setChoiceMode(ListView.CHOICE_MODE_SINGLE) 如何取消选择?