【问题标题】:RecyclerView messing up indicesRecyclerView 搞乱了索引
【发布时间】:2016-09-22 05:27:09
【问题描述】:

我有一个RecyclerView,滚动后,我的adapter 中的项目值正在交换。这显然是视图回收的问题,底层数据没有被清除。

但是,我已经阅读了这个问题的数十次迭代,但无法从任何答案中解读出明确的解决方法,而且我的问题仍然存在。

我将 Adapter 设置为具有稳定 ID,覆盖 getItemgetItemIdgetItemCount 方法,并且 - 我认为 - 对我的 onBindViewHolder 方法执行正确检查以判断我的数据是否干净......但最后一部分让我感到困惑,因为我不确定我应该在什么条件下执行我的条件(我觉得这些问题的大部分答案都缺乏)......

以下是一些相关代码:

public class MenuQueryAdapter extends ParseRecyclerQueryAdapter<MenuItem, MenuQueryAdapter.MenuViewHolder> {

    public MenuQueryAdapter(ParseQueryAdapter.QueryFactory<MenuItem> factory, boolean hasStableIds) {
        super(factory, hasStableIds);// hasStableIds set to TRUE
    }


    @Override
    public MenuViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        return new MenuViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.menu_item, parent, false));
    }

    @Override
    public void onBindViewHolder(MenuViewHolder holder, int position) {
        MenuItem menuItem = getItem(position);
        holder.bindItem(menuItem);
    }

    @Override
    public MenuItem getItem(int position) {
        //return super.getItem(position);
        if (menuItemList != null && menuItemList.size() > 0) {
            return menuItemList.get(position);
        }
        return super.getItem(position);
    }

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


    // View Holder
    public static class MenuViewHolder extends RecyclerView.ViewHolder {

        MenuItem menuItem;

        TextView title;
        TextView price;
        TextView summary;
        TextView itemCount;

        TextView  calorieLabel;
        TextView  proteinLabel;
        TextView  fatLabel;
        TextView  carbsLabel;
        TextView  fiberLabel;

        ParseImageView imageView;

        private String objectId = "";
        private boolean active = true;
        private boolean inStock = true;
        private boolean cSoon = false;
        private boolean hasNutrition = false;


        MenuViewHolder(View itemView) {
            super(itemView);

            title = (TextView) itemView.findViewById(R.id.menu_title_label);
            price = (TextView) itemView.findViewById(R.id.menu_price_label);
            summary = (TextView) itemView.findViewById(R.id.menu_summary);

            calorieLabel = (TextView) itemView.findViewById(R.id.menu_label_calorie_value);
            proteinLabel = (TextView) itemView.findViewById(R.id.menu_label_protein_value);
            fatLabel = (TextView) itemView.findViewById(R.id.menu_label_fat_value);
            carbsLabel = (TextView) itemView.findViewById(R.id.menu_label_carbs_value);
            fiberLabel = (TextView) itemView.findViewById(R.id.menu_label_fibre_value);

            imageView = (ParseImageView) itemView.findViewById(R.id.menu_main_image);

            // Containers
            final RelativeLayout activeView = (RelativeLayout) itemView.findViewById(R.id.menu_top_view_active);
            final RelativeLayout inactiveView = (RelativeLayout) itemView.findViewById(R.id.menu_top_view_inactive);

            View.OnClickListener clickListener = new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    active = !active;
                    if(active)
                    {
                        activeView.setVisibility(View.VISIBLE);
                        inactiveView.setVisibility(View.INVISIBLE);
                    }
                    else
                    {
                        activeView.setVisibility(View.INVISIBLE);
                        inactiveView.setVisibility(View.VISIBLE);
                    }
                }
            };

            final RelativeLayout topView = (RelativeLayout) itemView.findViewById(R.id.menu_top_view);
            topView.setOnClickListener(clickListener);

            final ImageButton info = (ImageButton) itemView.findViewById(R.id.menu_info_button);
            info.setOnClickListener(clickListener);

        }

        public void bindItem(MenuItem item) {
            menuItem = item;

            menuItem.populateData(); // gets data from DB

            // THIS IS MY CHECK TO SEE IF THE DATA SHOULD EB RECYCLED
            if( !menuItem.getTitle().equals(enroot.getContext().getResources().getString(R.string.menu_title)) ) {
                title.setText(menuItem.getTitle());
                price.setText(String.valueOf(menuItem.getPrice()));
                summary.setText(menuItem.getSummary());
                calorieLabel.setText(menuItem.getCalories());
                proteinLabel.setText(menuItem.getProtein());
                fatLabel.setText(menuItem.getFat());
                carbsLabel.setText(menuItem.getCarbs());
                fiberLabel.setText(menuItem.getFibre());
                imageView.setParseFile(menuItem.getImage());
                imageView.loadInBackground();

                if (menuItem.getInt(EnrootConstants.kERItemInStockKey) <= 0) {
                    inStock = false;
                }
                if (menuItem.getBoolean(EnrootConstants.kERItemComingSoonKey) && inStock) {
                    cSoon = true;
                }
                if (menuItem.getList(EnrootConstants.kERItemNutritionKey) != null && menuItem.getList(EnrootConstants.kERItemNutritionKey).size() > 0) {
                    hasNutrition = true;
                }

                // Id
                objectId = menuItem.getObjectId();
                if (mOnItemChangedListener != null) {
                    mOnItemChangedListener.passIdToActivity(objectId);
                }

                // Stock
                RelativeLayout ooStock = (RelativeLayout) itemView.findViewById(R.id.menu_soldout);
                if (!inStock) {
                    ooStock.setVisibility(View.VISIBLE);
                }

                // Coming Soon
                RelativeLayout comingSoon = (RelativeLayout) itemView.findViewById(R.id.menu_comingsoon);
                if (cSoon) {
                    comingSoon.setVisibility(View.VISIBLE);
                }

                // Nutrition
                if (!hasNutrition) {
                    RelativeLayout nutritionOverlay = (RelativeLayout) itemView.findViewById(R.id.menu_nutrition_group);
                    nutritionOverlay.setVisibility(View.INVISIBLE);
                }

                // Minus
                final ImageButton minus = (ImageButton) itemView.findViewById(R.id.menu_btn_minus);
                if (inStock && !cSoon) {
                    minus.setOnClickListener(new View.OnClickListener() {
                        @Override
                        public void onClick(View v) {
                            if (mOnItemChangedListener != null) {
                                mOnItemChangedListener.onPriceSubtracted(objectId, getAdapterPosition());
                            }
                        }
                    });
                } else {
                    minus.setVisibility(View.INVISIBLE);
                    minus.setEnabled(false);
                    minus.setClickable(false);
                }

                // Plus
                final ImageButton plus = (ImageButton) itemView.findViewById(R.id.menu_btn_plus);
                if (inStock && !cSoon) {
                    plus.setOnClickListener(new View.OnClickListener() {
                        @Override
                        public void onClick(View v) {
                            if (mOnItemChangedListener != null) {
                                mOnItemChangedListener.onPriceAdded(objectId, getAdapterPosition());
                            }
                        }
                    });
                } else {
                    plus.setVisibility(View.INVISIBLE);
                    plus.setEnabled(false);
                    plus.setClickable(false);
                }
            }
            else {
                clearItem();
            }
        }

        void clearItem() {

            title.setText("");
            price.setText("");
            summary.setText("");
            calorieLabel.setText("");
            proteinLabel.setText("");
            fatLabel.setText("");
            carbsLabel.setText("");
            fiberLabel.setText("");

            objectId = "";
            active = true;
            inStock = true;
            cSoon = false;
            hasNutrition = false;

        }

    } /* eoc holder */

    } /* eoc adapter */

所以...我看到很多关于简单地覆盖 getItem 和/或 getItemId 的讨论(如果您有稳定的 ID,这很有意义),但这似乎没有任何效果。我什至在ViewHolder 上将setIsRecyclable 设置为false,但没有效果。

我被卡住了...很想听听我是否做错了什么...

【问题讨论】:

  • 只有在您的标题条件失败时才尝试始终调用 clearItem。还要检查您的标题条件,将当前标题与静态标题进行比较看起来很奇怪。
  • 与静态标题的比较是因为我使用该字符串资源作为 XML 视图的文本 - 如果我将其设置为 null,我将无法看到它,所以这是一个占位符.所以这是代替 !TextUtils.isEmpty() 等
  • 所以...总是很清楚?那我在什么条件下设置我的数据对象的值呢?
  • menuItemList 填充了什么?
  • 啊。那是一个实验,你可以忽略它......但本质上它是由我从数据库中获得的查询结果填充的。这个 Adapter 子类化的底层类 - 并且它本身位于 RecyclerView 已经在一个通用类型列表中包含这些项目......

标签: android listview android-recyclerview android-adapter


【解决方案1】:

我认为您错过了返回项目计数

@Override
public int getItemCount() {
   return menuItemList.size();
}

【讨论】:

  • 不,不是这样 - 这是我在适配器和回收站视图之间的类...
猜你喜欢
  • 2022-01-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-03-19
  • 2017-07-12
  • 1970-01-01
  • 1970-01-01
  • 2017-12-10
相关资源
最近更新 更多