为 RecyclerView 实现不同的布局,但在 onBindViewHolder 上出现 class 投射错误

Implementing different layouts for RecyclerView but getting class cast erro on onBindViewHolder

我正在关注 this tutorial,但我收到以下转换错误:

java.lang.ClassCastException: com.banshai.appetit.controllers.home.OpenRestaurantsViewHolder cannot be cast to com.banshai.appetit.controllers.home.FirstOpenRestaurantVHolder at com.banshai.appetit.controllers.home.RestaurantAdapter.onBindViewHolder

尝试投射时在 onBindViewHolder 调用错误:FirstOpenRestaurantVHolder firstVH = (FirstOpenRestaurantVHolder) viewholder;。我错过了什么?

这是我的完整适配器:

public class RestaurantAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {

    private List<Restaurant> restaurants;
    private Context context;
    private SharedData sharedData;

    private final int FIRST_OPEN_RESTAURANT = 0;
    private final int OPEN_RESTAURANT = 1;

    public RestaurantAdapter(List<Restaurant> restaurantsList) {
        restaurants = restaurantsList;
        sharedData = SharedData.getInstance();
    }

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

    @Override
    public int getItemViewType(int position) {

        //If position is 0 this means we need to use FirstOpenRestaurantVHolder
        if (position == 0) {
            return FIRST_OPEN_RESTAURANT;

        } else if (position > 0) {
            return OPEN_RESTAURANT;
        }


        return OPEN_RESTAURANT; //TODO ojo con este default
    }

    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) {

        RecyclerView.ViewHolder viewHolder;
        LayoutInflater inflater = LayoutInflater.from(viewGroup.getContext());

        switch (viewType) {
            case FIRST_OPEN_RESTAURANT:

                View firstOpenRest = inflater.inflate(R.layout.intro_home_restaurant_first_card, viewGroup, false);
                viewHolder = new OpenRestaurantsViewHolder(firstOpenRest);
                break;

            case OPEN_RESTAURANT: //TODO ojo este no va ser el default
                View openRest = inflater.inflate(R.layout.intro_home_resturant_card_row, viewGroup, false);
                viewHolder = new FirstOpenRestaurantVHolder(openRest);
                break;

            default:
                View openRestaurant = inflater.inflate(R.layout.intro_home_resturant_card_row, viewGroup, false);
                viewHolder = new FirstOpenRestaurantVHolder(openRestaurant);
                break;

        }

        return viewHolder;
    }

    @Override
    public void onBindViewHolder(RecyclerView.ViewHolder viewholder, int position) {
        switch (viewholder.getItemViewType()) {

            case FIRST_OPEN_RESTAURANT:
                FirstOpenRestaurantVHolder firstVH = (FirstOpenRestaurantVHolder) viewholder;
                firstVH.franchiseName.setText("FIRST!!!");


                break;

            default:
                OpenRestaurantsViewHolder openVH = (OpenRestaurantsViewHolder) viewholder;
                openVH.franchiseName.setText("OPEN BUT NOT FIRST");
                break;
        }
    }

    public class OpenRestaurantsViewHolder extends RecyclerView.ViewHolder {

        protected TextView franchiseName;
        protected TextView homeCategory;
        protected ImageView restaurantPhoto;
        protected ImageView franchiseLogo;


        public OpenRestaurantsViewHolder(View view) {
            super(view);

            franchiseName = (TextView) view.findViewById(R.id.home_franchise_name);
            restaurantPhoto = (ImageView) view.findViewById(R.id.home_resturant_pic);
            franchiseLogo = (ImageView) view.findViewById(R.id.home_franchise_logo);
            homeCategory = (TextView) view.findViewById(R.id.home_category);


        }
    }

    public class FirstOpenRestaurantVHolder extends RecyclerView.ViewHolder {

        protected TextView franchiseName;
        protected TextView homeCategory;
        protected ImageView restaurantPhoto;
        protected ImageView franchiseLogo;


        public FirstOpenRestaurantVHolder(View view) {
            super(view);

            franchiseName = (TextView) view.findViewById(R.id.home_first_franchise_name);
            restaurantPhoto = (ImageView) view.findViewById(R.id.home_first_resturant_pic);
            franchiseLogo = (ImageView) view.findViewById(R.id.home_first_franchise_logo);
            homeCategory = (TextView) view.findViewById(R.id.home_first_category);
        }


    }
}

问题在这里:

case FIRST_OPEN_RESTAURANT:
  FirstOpenRestaurantVHolder firstVH = (FirstOpenRestaurantVHolder) viewholder; 

onCreateViewHolder 中设置 OpenRestaurantsViewHolderFIRST_OPEN_RESTAURANT 的情况下,但在 onBindViewHolder 中将 getTag 值转换为 FirstOpenRestaurantVHolder :

case FIRST_OPEN_RESTAURANT:
      OpenRestaurantsViewHolder firstVH = (OpenRestaurantsViewHolder) viewholder;

不得不更改您的 if 代码而不是 switch 以使其更清晰(这只是个人偏好),添加了一些控制台日志以查看发生了什么,但这应该有效:

public class RestaurantAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {

    private List<Restaurant> restaurants;
    private Context context;
    private SharedData sharedData;

    private final int FIRST_OPEN_RESTAURANT = 0;
    private final int OPEN_RESTAURANT = 1;

    public RestaurantAdapter(List<Restaurant> restaurantsList) {
        restaurants = restaurantsList;
        sharedData = SharedData.getInstance();
    }

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

    @Override
    public int getItemViewType(int position) {
        Log.i("getItemVi(position)", "position=" + position);
        //If position is 0 this means we need to use FirstOpenRestaurantVHolder
        if (position == 0) {
            return 0;

        } else if (position > 0) {
            return 1;
        }


        return 1; //TODO ojo con este default
    }

    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) {
        Log.i("onCreateVewHo(viewType)", "viewType=" + viewType);

        RecyclerView.ViewHolder viewHolder;
        LayoutInflater inflater = LayoutInflater.from(viewGroup.getContext());

        if (viewType == 0) {
            View firstOpenRest = inflater.inflate(R.layout.intro_home_restaurant_first_card, viewGroup, false);
            viewHolder = new FirstOpenRestaurantVHolder(firstOpenRest);

        } else {
            View openRestaurant = inflater.inflate(R.layout.intro_home_resturant_card_row, viewGroup, false);
            viewHolder = new OpenRestaurantsViewHolder(openRestaurant);
        }

        return viewHolder;
    }

    @Override
    public void onBindViewHolder(RecyclerView.ViewHolder viewholder, int position) {
        Log.i("onBindViewHolder", "viewholder.getItemViewType()=" + viewholder.getItemViewType());

        if (viewholder.getItemViewType() == 0) {
            FirstOpenRestaurantVHolder firstVH = (FirstOpenRestaurantVHolder) viewholder;
            firstVH.franchiseName.setText("FIRST!!!");

        } else {
            OpenRestaurantsViewHolder openVH = (OpenRestaurantsViewHolder) viewholder;
            openVH.franchiseName.setText("OPEN BUT NOT FIRST");

        }
    }

    public class OpenRestaurantsViewHolder extends RecyclerView.ViewHolder {

        protected TextView franchiseName;
        protected TextView homeCategory;
        protected ImageView restaurantPhoto;
        protected ImageView franchiseLogo;


        public OpenRestaurantsViewHolder(View view) {
            super(view);
            franchiseName = (TextView) view.findViewById(R.id.home_franchise_name);
            restaurantPhoto = (ImageView) view.findViewById(R.id.home_resturant_pic);
            franchiseLogo = (ImageView) view.findViewById(R.id.home_franchise_logo);
            homeCategory = (TextView) view.findViewById(R.id.home_category);

        }
    }

    public class FirstOpenRestaurantVHolder extends RecyclerView.ViewHolder {

        protected TextView franchiseName;
        protected TextView homeCategory;
        protected ImageView restaurantPhoto;
        protected ImageView franchiseLogo;


        public FirstOpenRestaurantVHolder(View view) {
            super(view);

            franchiseName = (TextView) view.findViewById(R.id.home_first_franchise_name);
            restaurantPhoto = (ImageView) view.findViewById(R.id.home_first_resturant_pic);
            franchiseLogo = (ImageView) view.findViewById(R.id.home_first_franchise_logo);
            homeCategory = (TextView) view.findViewById(R.id.home_first_category);
        }


    }
}