Java 无条件布局,视图适配器膨胀:应该使用 View Holder 模式

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/25381435/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 00:16:59  来源:igfitidea点击:

Unconditional layout, inflation from view adapter: Should use View Holder pattern

javaandroidlayout-inflater

提问by TheDevMan

I am getting following warning in eclipse:

我在 Eclipse 中收到以下警告:

Unconditional layout inflation from view adapter: Should use View Holder pattern (use recycled view passed into this method as the second parameter) for smoother scrolling.

来自视图适配器的无条件布局膨胀:应该使用 View Holder 模式(使用传递给此方法的回收视图作为第二个参数)以获得更平滑的滚动。

on:

在:

convertView = vi.inflate(R.layout.activity_friend_list_row, parent, false);

I have a base adapter with a CheckBox implemented and I have added a tag to make the CheckBox work.

我有一个带有 CheckBox 的基本适配器,并且我添加了一个标签来使 CheckBox 工作。

Here is the code:

这是代码:

 public View getView(final int position, View convertView, ViewGroup parent) 
  {

    ViewHolder mViewHolder;
    mViewHolder = new ViewHolder();
    LayoutInflater vi = (LayoutInflater) activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);

    convertView = vi.inflate(R.layout.activity_friend_list_row, parent, false);

    mViewHolder.cb = (CheckBox) convertView.findViewById(R.id.checkBox);

    convertView.setTag(mViewHolder);

    if (InviteFriends.isChecked[position] == true)
    {
        mViewHolder.cb.setChecked(true);
    }
    else
    {
        mViewHolder.cb.setChecked(false);
    }

    mViewHolder.cb.setOnCheckedChangeListener(new OnCheckedChangeListener() 
    {
        @Override
        public void onCheckedChanged(CompoundButton buttonView, boolean ischecked) 
        {
            if (buttonView.isChecked())
            {
                InviteFriends.isChecked[position] = true;

            }
            else
            {
                InviteFriends.isChecked[position] = false;
            }
        }
    });

    TextView friendsname  = (TextView) convertView.findViewById(R.id.friendsName); // title
    ImageView thumb_image = (ImageView) convertView.findViewById(R.id.list_image); // thumb image

    HashMap<String, String> song = new HashMap<String, String>();
    song = data.get(position);

    // Setting all values in listview
    friendsname.setText(song.get(InviteFriends.KEY_DISPLAY_NAME));
    imageLoader.DisplayImage(song.get(InviteFriends.KEY_IMAGEPROFILE_URL), thumb_image);


    return convertView;
}

The results are coming up properly. How do I fix this warning? I am not able to get a solution for this yet?

结果正确出现。如何修复此警告?我还没有办法解决这个问题吗?

Thanks!

谢谢!

采纳答案by Sonali8890

Try this

尝试这个

static class ViewHolder {

    private TextView friendsname;
    private ImageView thumb_image;
    private CheckBox cb;

}
public View getView(final int position, View convertView, ViewGroup parent) {

    ViewHolder mViewHolder = null;
    HashMap<String, String> song = null;

    if (convertView == null) {

        song = new HashMap <String, String>();
        mViewHolder = new ViewHolder();

        LayoutInflater vi = (LayoutInflater) activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);

        convertView = vi.inflate(R.layout.activity_friend_list_row, parent, false);
        mViewHolder.friendsname = (TextView) convertView.findViewById(R.id.friendsName); // title
        mViewHolder.thumb_image = (ImageView) convertView.findViewById(R.id.list_image); // thumb image


        mViewHolder.cb = (CheckBox) convertView.findViewById(R.id.checkBox);

        convertView.setTag(mViewHolder);
        mViewHolder.cb.setTag(data.get(position));

        mViewHolder.cb.setOnCheckedChangeListener(new OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(CompoundButton buttonView, boolean ischecked) {

                InviteFriends.isChecked[position] = buttonView.isChecked();

            }
        });

    } else {

        mViewHolder = (ViewHolder) convertView.getTag();

    }

    song = mViewHolder.cb.getTag();

    mViewHolder.friendsname.setText(song.get(InviteFriends.KEY_DISPLAY_NAME));
    mViewHolder.imageLoader.DisplayImage(song.get(InviteFriends.KEY_IMAGEPROFILE_URL), thumb_image);
    mViewHolder.cb.setChecked(InviteFriends.isChecked[position]);

    return convertView;
}

回答by Jithu

My suggestion is try to use convertView = vi.inflate(R.layout.activity_friend_list_row, null);insted of convertView = vi.inflate(R.layout.activity_friend_list_row, parent, false);this may help you.

我的建议是尝试使用convertView = vi.inflate(R.layout.activity_friend_list_row, null);instedconvertView = vi.inflate(R.layout.activity_friend_list_row, parent, false);这可能会帮助你。

:- okey.. insted of accessing like this TextView friendsname = (TextView) convertView.findViewById(R.id.friendsName); // title ImageView thumb_image = (ImageView) convertView.findViewById(R.id.list_image); // thumb image you have to use viewholder class in your adapter

:- 好吧.. 像这样访问TextView friendsname = (TextView) convertView.findViewById(R.id.friendsName); // title ImageView thumb_image = (ImageView) convertView.findViewById(R.id.list_image); // thumb image 你必须在你的适配器中使用 viewholder 类

for example

例如

static class ViewHolder {
    public TextView text;
    public ImageView image;
  }

  @Override
  public View getView(int position, View convertView, ViewGroup parent) {
    View rowView = convertView;
    // reuse views
    if (rowView == null) {
      LayoutInflater inflater = context.getLayoutInflater();
      rowView = inflater.inflate(R.layout.rowlayout, null);
      // configure view holder
      ViewHolder viewHolder = new ViewHolder();
      viewHolder.text = (TextView) rowView.findViewById(R.id.TextView01);
      viewHolder.image = (ImageView) rowView
          .findViewById(R.id.ImageView01);
      rowView.setTag(viewHolder);
    }

    // fill data
    ViewHolder holder = (ViewHolder) rowView.getTag();
    String s = names[position];
    holder.text.setText(s);
    if (s.startsWith("Windows7") || s.startsWith("iPhone")
        || s.startsWith("Solaris")) {
      holder.image.setImageResource(R.drawable.no);
    } else {
      holder.image.setImageResource(R.drawable.ok);
    }

    return rowView;
  }

回答by ungalcrys

you should init the convert view only if it is null

只有当它为空时才应该初始化转换视图

these lines

这些线

LayoutInflater vi = (LayoutInflater) activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);

convertView = vi.inflate(R.layout.activity_friend_list_row, parent, false);
// [...] the rest of initialization part
// [...] some changes that must be done at refresh
return convertView;

should look like this:

应该是这样的:

if (convertView == null) {
    LayoutInflater vi = (LayoutInflater) activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);

    convertView = vi.inflate(R.layout.activity_friend_list_row, parent, false);
    // [...] the rest of initialization part
}
// [...] some changes that must be done at refresh
return convertView;

the goal is to recycle the already existing view in that list, not to init it each time you display it when scrolling the list for example.

目标是回收该列表中已经存在的视图,而不是在滚动列表时每次显示它时初始化它。

回答by ??? ???? ????

Unconditional layout inflation from view adapter: Should use View Holder pattern (use recycled view passed into this method as the second parameter) for smoother scrolling.

来自视图适配器的无条件布局膨胀:应该使用 View Holder 模式(使用传递给此方法的回收视图作为第二个参数)以获得更平滑的滚动。

It means that you need to use View Holder pattern in your Adapter. The point of using View Holder is to reusing the views because inflating and using findViewByIdare slow.

这意味着您需要在 Adapter 中使用 View Holder 模式。使用 View Holder 的目的是重用视图,因为膨胀和使用findViewById都很慢。

When you're using the following code:

当您使用以下代码时:

public View getView(final int position, View convertView, ViewGroup parent) {

    ViewHolder mViewHolder;
    mViewHolder = new ViewHolder();
    LayoutInflater vi = (LayoutInflater) activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    convertView = vi.inflate(R.layout.activity_friend_list_row, parent, false);
    mViewHolder.cb = (CheckBox) convertView.findViewById(R.id.checkBox);
    convertView.setTag(mViewHolder);

    ...

    return convertView;

} 

you're not reusing the views but instead you always create new views.

您没有重用视图,而是始终创建新视图。

You need to change your code to something like this (please check the comment):

您需要将代码更改为这样的内容(请查看评论):

// class for holding the cached view
static class ViewHolder {
   TextView tvFriendsName;
   ImageView imvThumbImage;
   CheckBox cbInviteFriend;
}

public View getView(final int position, View convertView, ViewGroup parent) {

    // holder of the views to be reused.
    ViewHolder viewHolder;

    // get data based on the position
    HashMap<String, String> song = data.get(position);

    // if no previous views found
    if (convertView == null) {
       // create the container ViewHolder
       viewHolder = new ViewHolder();

       // inflate the views from layout for the new row
       LayoutInflater inflater = LayoutInflater.from(parent.getContext());
       convertView = inflater.inflate(R.layout.rowlayout, parent, false);

       // set the view to the ViewHolder.
       viewHolder.cbInviteFriend = convertView.findViewById(R.id.checkBox);
       viewHolder.tvFriendsName  = convertView.findViewById(R.id.friendsName);
       viewHolder.imvThumbImage = convertView.findViewById(R.id.list_image); 

       // save the viewHolder to be reused later.
       convertView.setTag(viewHolder);
    } else {
       // there is already ViewHolder, reuse it.
       viewHolder = (ViewHolder) convertView.getTag();
    }

    // now we can set populate the data via the ViewHolder into views
    viewHolder.tvFriendsName.setText(song.get(InviteFriends.KEY_DISPLAY_NAME));
    imageLoader.DisplayImage(song.get(InviteFriends.KEY_IMAGEPROFILE_URL), viewHolder.imvThumbImage);
    viewHolder.cbInviteFriend.isChecked(InviteFriends.isChecked[position]);

    return convertView;
}