RecyclerView.Adapter - 显示的数据不正确

时间:2016-10-25 09:30:13

标签: android android-recyclerview

我在使用RecyclerView.Adapter时遇到了一些麻烦。问题是RecyclerView有时会混淆视图,但不会与底层数据混合,而是显示内容。它只发生在屏幕上大约5%的项目上。有时TextViews完全从外部空间获取文本,例如它假设显示“1”但显示“50”但该数字在应用程序中的任何位置都不存在,因为文本在我创建项目时自动增量而且我已经得到了两个,当我检查数据库中的哪些项目在哪个位置一切都很好,什么更多的时候,当我调试onBindViewHolder时,持有者获得了所有正确的数据,并将其设置为视图,但是屏幕有所不同,所以看起来错误是在onBindViewHolder之后的某个地方生成的。为了清楚起见,我正在实现所有方法getItemId,hasStableIds,getItem,它们确实为onBindViewHolder中的给定位置返回正确的项目。

@Override
public void onBindViewHolder(ItemViewHolder holder, int position) {
    Item item = mProvider.getItem(position);
    int stickerSize = (int) (screenWidth * Const.STICKER_GRID_PROP);
    Picasso.with(mContext)
            .load(Const.backgroundNoteIDs[item.backgroundId])
            .into(holder.background);
    Picasso.with(mContext)
            .load(Const.stickerIDs[item.stickerId])
            .resize(stickerSize, stickerSize)
            .centerInside()
            .into(holder.sticker);
    int paddingHorizontal = (int) (screenWidth * Const.GRID_TEXT_PADDING_HORIZONTAL_PROP);
    int paddingVertical = (int) (screenWidth * Const.GRID_TEXT_PADDING_VERTICAL_PROP);

    switch(item.type) {
        case Const.NOTE:
            holder.noteText.setText(item.note.text);
            holder.checklistItemsLayout.removeAllViews();
            holder.checklistLines.setImageBitmap(null);
            holder.noteText.setTextSize(screenWidth * Const.GRID_TEXT_SIZE_PROP);
            holder.noteText.setPadding(paddingHorizontal, paddingVertical, paddingHorizontal, paddingVertical);
            break;
        case Const.CHECKLIST:
            holder.noteText.setText(null);
            holder.checklistItemsLayout.setPadding(paddingHorizontal, paddingVertical, paddingHorizontal, paddingVertical);
            Iterator<ChecklistItem> it = item.checklist.checklistItems.iterator();
            int i = 0;
            while(it.hasNext() && i < 4)
            {
                ChecklistItem checklistItem = it.next();
                final TextView textView = new TextView(mContext);
                textView.setEllipsize(TextUtils.TruncateAt.END);
                textView.setText(checklistItem.text);
                int drawable;
                if(checklistItem.checkStatement) {
                    drawable = R.drawable.checked;
                } else {
                    drawable = R.drawable.unchecked;
                }
                Picasso.with(mContext)
                        .load(drawable)
                        .resize((int) (stickerSize * 0.25f), (int) (stickerSize * 0.25f))
                        .centerInside()
                        .into(new Target() {
                            @Override
                            public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom from) {
                                Drawable d = new BitmapDrawable(mResources, bitmap);
                                textView.setCompoundDrawablesWithIntrinsicBounds(d, null, null, null);
                            }

                            @Override
                            public void onBitmapFailed(Drawable errorDrawable) {

                            }

                            @Override
                            public void onPrepareLoad(Drawable placeHolderDrawable) {

                            }
                        });
                Picasso.with(mContext)
                        .load(R.drawable.karteczka_linie)
                        .resize( (int) (screenWidth * Const.MENU_BIG_BUTTON_PROP), (int) (screenWidth * Const.MENU_BIG_BUTTON_PROP))
                        .centerInside()
                        .into(holder.checklistLines);
                textView.setTextSize(screenWidth * Const.GRID_TEXT_SIZE_PROP);
                holder.checklistItemsLayout.addView(textView);
                i++;
            }
            break;
        default:
            throw new IllegalArgumentException("onBindViewHolder got item without any type");
    }
}
public Item getItem(int index) {
    return mItems.get(index);
}
public static class ItemViewHolder extends RecyclerView.ViewHolder implements
        ItemTouchHelperViewHolder {
    public TextView noteText;
    public ImageView background;
    public ImageView checklistLines;
    public ImageView sticker;
    public LinearLayout checklistItemsLayout;

    public ItemViewHolder(View itemView) {
        super(itemView);
        noteText = (TextView) itemView.findViewById(R.id.note_text);
        background = (ImageView) itemView.findViewById(R.id.note_background);
        checklistLines = (ImageView) itemView.findViewById(R.id.checklist_lines);
        sticker = (ImageView) itemView.findViewById(R.id.note_sticker);
        checklistItemsLayout = (LinearLayout) itemView.findViewById(R.id.checklist_items);
        itemView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Log.d(TAG, "onClick " + getItemId());
            }
        });
    }

    @Override
    public void onItemSelected() {
        itemView.setBackgroundColor(Color.LTGRAY);
    }

    @Override
    public void onItemClear() {
        itemView.setBackgroundColor(0);
    }
}

1 个答案:

答案 0 :(得分:0)

Okey,所以这是解决方案,我忘了从ViewHolder中的checklistItemsLayout中删除所有视图,这会扩展我显示的两种类型的项目之一,因此每次特定的 ViewHolder被重用,TextViews是添加得当但是它们堆叠在旧的上面,所以它们没有空间显示,但只有当ViewHolder在相同类型的项目上重复使用时才会发生这种情况。

您需要记住在onBindViewHolder中重新加载ViewHolder中的每个元素,否则您可能会像之前在此ViewHolder中使用的其他项目中剩余一些剩余部分

这是固定代码:

@Override
public void onBindViewHolder(ItemViewHolder holder, int position) {
    ...

    switch(item.type) {
        case Const.NOTE:
            holder.noteText.setText(item.note.text);
            holder.checklistItemsLayout.removeAllViews();
            holder.checklistLines.setImageBitmap(null);
            holder.noteText.setTextSize(screenWidth * Const.GRID_TEXT_SIZE_PROP);
            holder.noteText.setPadding(paddingHorizontal, paddingVertical, paddingHorizontal, paddingVertical);
            break;
        case Const.CHECKLIST:

            //This line was missing
            holder.checklistItemsLayout.removeAllViews();

            holder.noteText.setText(null);
            holder.checklistItemsLayout.setPadding(paddingHorizontal, paddingVertical, paddingHorizontal, paddingVertical);
            Iterator<ChecklistItem> it = item.checklist.checklistItems.iterator();
            int i = 0;
            while(it.hasNext() && i < 4)
            {
             ...
            }

    }
}