安卓ListView中的ViewHolder:何时使用,何时不使用

8
我有一个带有自定义列表适配器的ListView。在getView()方法中,我使用了ViewHolder“模式”,就像ListView14.java中的API演示所示。当我首次呈现列表时,它似乎加载正确。然而,我遇到的问题是,当我滚动列表时,我看到列表数据出现在错误的行中(例如,应该在第10行的TextView出现在第2行)。但是,当我不使用viewholder,而是每次调用findViewById()时,列表视图会正确呈现。
3个回答

10
然而,我遇到的问题是,当我滚动列表时,我看到列表数据出现在错误的行中(例如,应该在第10行的TextView出现在第2行)。

很可能,您正在不正确地回收行,以至于您正在操作的ViewHolders不是您返回的行的正确ViewHolders。

这是我的一本书的免费节选,其中更多关于行回收的内容--也许它将帮助您确定问题出在哪里。


2
  • I faced same problem
  • Solved using below techninc
  • Reason : Adapter not Loaded Frequentlyy.
  • in Your Custom Adapter class add ViewHolder using Access Specifiers

    private static class ViewHolder {
    
            protected TextView itemName;
    
        }
    
获取视图方法 中:
    @Override

        public View getView(int position, View view, ViewGroup viewGroup) {

            // create a ViewHolder reference
            ViewHolder holder;

            //check to see if the reused view is null or not, if is not null then reuse it
            if (view == null) {
                holder = new ViewHolder();

                view = mLayoutInflater.inflate(R.layout.list_item, null);
                holder.itemName = (TextView) view.findViewById(R.id.list_item_text_view);

                // the setTag is used to store the data within this view
                view.setTag(holder);
            } else {
                // the getTag returns the viewHolder object set as a tag to the view
                holder = (ViewHolder)view.getTag();
            }
    // now Use Holder object toget Idss 

    holder.itemName.setText(" sample text based on position ");
    }

重要提示:除了 Viewholder 对象,我们不应该为视图对象设置任何标签。


1

所以我认为我发现了真正的问题。当您为每一行动态设置布局参数时,需要确保对所有条件都进行设置。我的问题是,如果是第一行,我设置了一个布局参数(如填充或边距等),但是如果是中间行,则没有显式设置这些参数,认为它会使用视图填充器填充的内容。这就解释了为什么每次膨胀视图时都能正常工作。以下是之前和之后的情况:

之前:

if (position == 0) {

            layoutParams.topMargin = uiHelper.getDip(15.0f);
            layoutParams.addRule(RelativeLayout.ALIGN_PARENT_TOP,
                    RelativeLayout.TRUE);
            holder.actionMenu.setLayoutParams(layoutParams);

            holder.contentLayout.setBackgroundResource(R.drawable.top_row);

        } else if (position == posts.size() - 1) {
            holder.contentLayout
                    .setBackgroundResource(R.drawable.bottom_row);

            holder.contentLayout.setPadding(holder.contentLayout
                    .getPaddingLeft(),
                    holder.contentLayout.getPaddingTop(),
                    holder.contentLayout.getPaddingRight(),
                    holder.contentLayout.getPaddingBottom() +  uiHelper.getDip(10.0f));

        } else {
            holder.contentLayout
                    .setBackgroundResource(R.drawable.inner_row);
        }

之后:

            layoutParams.topMargin = uiHelper.getDip(10.0f);
        holder.contentLayout.setPadding(holder.contentLayout
                .getPaddingLeft(),
                holder.contentLayout.getPaddingTop(),
                holder.contentLayout.getPaddingRight(),
                uiHelper.getDip(10.0f));
        if (position == 0) {

            layoutParams.topMargin = uiHelper.getDip(15.0f);
            layoutParams.addRule(RelativeLayout.ALIGN_PARENT_TOP,
                    RelativeLayout.TRUE);

            holder.contentLayout.setBackgroundResource(R.drawable.top_row);

        } else if (position == posts.size() - 1) {
            holder.contentLayout
                    .setBackgroundResource(R.drawable.bottom_row);

            holder.contentLayout.setPadding(holder.contentLayout
                    .getPaddingLeft(),
                    holder.contentLayout.getPaddingTop(),
                    holder.contentLayout.getPaddingRight(),
                    uiHelper.getDip(20.0f));

        } else {

            holder.contentLayout
                    .setBackgroundResource(R.drawable.inner_row);

        }

        holder.actionMenu.setLayoutParams(layoutParams);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接