【问题标题】:ListView recycling view feature affects the other items in the listListView 回收视图功能影响列表中的其他项目
【发布时间】:2014-07-15 11:04:54
【问题描述】:

我正在开发一个使用 ListView 来显示用户及其个人资料的 android 应用程序。您可以在下面的图片中看到它的实际外观。可能有大量用户,所以我实现了延迟加载功能,一次加载四个用户。当应用程序启动时(列表中有 4 个用户),一切看起来都很好,但是在我向下滚动并加载接下来的四个用户后,发生了一些奇怪的事情。正如您在图像上看到的,每个用户都有自己的棋子,例如,其中一些人有眼镜,而另一些人没有。滚动后,似乎新加载的用户或其中一些用户也有眼镜,虽然他们不应该有。

http://pasteboard.co/1xs78l6C.png

我可以猜到问题的发生是因为适配器回收了视图。视图由许多图像组成,我认为在没有此功能(回收)的情况下实现适配器并不是一个好主意。另一方面,我对它没有很好的经验,我不知道应该注意哪里来防止这种行为。如有任何帮助或建议如何解决此问题,我将不胜感激。

在这里你可以看到我的适配器是什么样子的

public class UserAdapter extends BaseAdapter {

    private final Context context;
    private ArrayList<User> users;

    private HashMap<String, Integer> resIds;

    private final int[] slotIds = { R.id.imgRowSlot1, R.id.imgRowSlot2,
            R.id.imgRowSlot3 };

    public UserAdapter(Context context) {
        this.context = context;
        users = new ArrayList<User>();
        resIds = new HashMap<String, Integer>(Config.init());
    }

    public void updateUsers(List<User> users) {
        this.users = new ArrayList<User>(users);
        notifyDataSetChanged();
    }

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

    @Override
    public User getItem(int position) {
        return users.get(position);
    }

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

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

        TextView txtFirstName;
        TextView txtLastName;

        ImageView imgSlot1;
        ImageView imgSlot2;
        ImageView imgSlot3;

        ImageView imgHead;
        ImageView imgGlasses;
        ImageView imgTop;
        ImageView imgBottom;

        if (convertView == null) {
            convertView = LayoutInflater.from(context).inflate(
                    R.layout.user_row, parent, false);

            txtFirstName = (TextView) convertView
                    .findViewById(R.id.txtFirstName);
            txtLastName = (TextView) convertView.findViewById(R.id.txtLastName);

            imgSlot1 = (ImageView) convertView.findViewById(R.id.imgRowSlot1);
            imgSlot2 = (ImageView) convertView.findViewById(R.id.imgRowSlot2);
            imgSlot3 = (ImageView) convertView.findViewById(R.id.imgRowSlot3);

            imgHead = (ImageView) convertView
                    .findViewById(R.id.imgHead_adapter);
            imgGlasses = (ImageView) convertView
                    .findViewById(R.id.imgGlasses_adapter);
            imgTop = (ImageView) convertView.findViewById(R.id.imgTop_adapter);
            imgBottom = (ImageView) convertView
                    .findViewById(R.id.imgBottom_adapter);

            convertView.setTag(new ViewHolder(txtFirstName, txtLastName,
                    imgSlot1, imgSlot2, imgSlot3, imgHead, imgGlasses, imgTop,
                    imgBottom));

        } else {

            ViewHolder viewHolder = (ViewHolder) convertView.getTag();
            txtFirstName = viewHolder.txtFirstName;
            txtLastName = viewHolder.txtLastName;

            imgSlot1 = viewHolder.imgSlot1;
            imgSlot2 = viewHolder.imgSlot2;
            imgSlot3 = viewHolder.imgSlot3;

            imgHead = viewHolder.imgHead;
            imgGlasses = viewHolder.imgGlasses;
            imgTop = viewHolder.imgTop;
            imgBottom = viewHolder.imgBottom;
        }

        User user = getItem(position);

        int[] slots = user.getSlots();

        // name
        txtFirstName.setText(user.getFirstName());
        txtLastName.setText(user.getLastName());

        // fruits
        imgSlot1.setImageResource(MyDataController.fruits[slots[0]]);
        imgSlot2.setImageResource(MyDataController.fruits[slots[1]]);
        imgSlot3.setImageResource(MyDataController.fruits[slots[2]]);
        FruitExtractor.setAlpha(convertView, slotIds, user);

        // pawn head
        if (user.getConsCounter() >= 2) {
            imgHead.setImageResource(R.drawable.head_happy_noeyes);
        } else if (user.getConsCounter() == 1) {
            imgHead.setImageResource(R.drawable.head_indiferent_noeyes);
        } else {
            imgHead.setImageResource(R.drawable.head_sad_noeyes);
        }

        // glasses
        if (user.getGlasses() != null) {
            imgGlasses.setImageResource(resIds.get(user.getGlasses()
                    .getResIdName()));
        }

        // body
        imgTop.setImageResource(resIds.get(user.getTop().getResIdName()));
        imgBottom.setImageResource(resIds.get(user.getBottom().getResIdName()));

        return convertView;
    }

    private static class ViewHolder {

        public final TextView txtFirstName;
        public final TextView txtLastName;

        public final ImageView imgSlot1;
        public final ImageView imgSlot2;
        public final ImageView imgSlot3;

        public final ImageView imgHead;
        public final ImageView imgGlasses;
        public final ImageView imgTop;
        public final ImageView imgBottom;

        public ViewHolder(TextView txtFirstName, TextView txtLastName,
                ImageView imgSlot1, ImageView imgSlot2, ImageView imgSlot3,
                ImageView imgHead, ImageView imgGlasses, ImageView imgTop,
                ImageView imgBottom) {
            this.txtFirstName = txtFirstName;
            this.txtLastName = txtLastName;
            this.imgSlot1 = imgSlot1;
            this.imgSlot2 = imgSlot2;
            this.imgSlot3 = imgSlot3;
            this.imgHead = imgHead;
            this.imgGlasses = imgGlasses;
            this.imgTop = imgTop;
            this.imgBottom = imgBottom;
        }
    }

    public List<User> getUsers() {
        return users;
    }
}

【问题讨论】:

    标签: android android-listview baseadapter


    【解决方案1】:
        // glasses
        if (user.getGlasses() != null) {
            imgGlasses.setImageResource(resIds.get(user.getGlasses()
                    .getResIdName()));
        }else{
             //there is no else statement to clear the previous glasses
             //you can do something like this
             imgGlasses.setImageResource(android.R.color.transparent);
        }
    

    【讨论】:

    • 我添加了这个else { imgGlasses.setImageDrawable(null); },在我看来,它工作正常。谢谢小费!
    • @am.sal 很高兴。为防止将来出现此类错误,请创建一个 ViewHolder.clear() 方法,在设置之前清除所有视图。
    猜你喜欢
    • 1970-01-01
    • 2017-03-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-11-07
    • 2012-07-02
    相关资源
    最近更新 更多