在具有多个ViewType的RecyclerView中显示项目时出错

时间:2018-10-26 09:12:25

标签: android android-recyclerview

我正在将Recyclerview与多个ViewTypes一起使用。我在recyclerview中有两个用于两个不同类型物品的Model类。我想在同一RecyclerView中显示两个不同类型的物品 我的RecyclerViewAdapter

public class RecyclerAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
        private Context context;
        ArrayList<OneView> oneList;
        ArrayList<TwoView> twoList;
        public RecyclerAdapter(Context context,ArrayList<OneView> oneList,ArrayList<TwoView> twoList){
            this.context=context;
            this.oneList=oneList;
            this.twoList=twoList;
        }    
        @Override
        public int getItemViewType(int position) {
            switch (position){
                case 0:
                    return 0;
                case 1:
                    return 1;
            }
            return -1;
        }
        @Override
        public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
            int layout=0;
            RecyclerView.ViewHolder viewHolder;
            if(viewType==0){
                layout=R.layout.oneview;
                View one= LayoutInflater.from(parent.getContext()).inflate(layout,parent,false);
                return new ViewHolder(one);
            }else if(viewType==1){
                layout=R.layout.twoview;
                View two= LayoutInflater.from(parent.getContext()).inflate(layout,parent,false);
                return new SecondView(two);
            }else {
                return null;
            }
        }    
        @Override
        public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
            int viewType=holder.getItemViewType();
            switch (viewType){
                case 0:
                    OneView  oneView=oneList.get(position);
                    ((ViewHolder)holder).name.setText(oneView.getName());
                    break;
                case 1:
                    TwoView twoView=twoList.get(position);
                    ((SecondView)holder).name.setText(twoView.getName());
                    ((SecondView)holder).address.setText(twoView.getAddress());
                    break;
                default:
                    break;
            }

        }

        @Override
        public int getItemCount() {
            return (this.oneList.size()+this.twoList.size());
        }

        public class ViewHolder extends RecyclerView.ViewHolder {
            private TextView name;
            public ViewHolder(View itemView) {
                super(itemView);
                name=(TextView)itemView.findViewById(R.id.nameOne);
            }
        }

        public class SecondView extends RecyclerView.ViewHolder {
            private TextView name,address;
            public SecondView(View itemView) {
                super(itemView);
                name=(TextView)itemView.findViewById(R.id.nameTwo);
                address=(TextView)itemView.findViewById(R.id.address);
            }
        }
    }  

我想在同一RecyclerView中显示两种类型的物品。但是我遇到了Attempt to write to field 'int android.support.v7.widget.RecyclerView$ViewHolder.mItemViewType' on a null object reference异常。如何解决呢?

1 个答案:

答案 0 :(得分:1)

这是完整的示例。我使用了具有多个视图类型的RecyclerView。我的场景是,我必须显示“美食清单”(这是多种美食的水平视图),然后显示“餐厅数量”,然后显示“餐厅清单”。

因此,我使用 VIEW_RESTAURANT 来查看餐厅,使用 VIEW_CUISINE 来烹饪, < em> VIEW_INFO 以获取餐厅数量。对于我的情况,有分页,因此 VIEW_PROGRESS 用于在底部显示进度条(到那时,将获取新数据集(如果有)), VIEW_NO_DATA

希望从这里开始,您可以根据需要进行管理。

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

private String TAG = HomeAdapter.class.getSimpleName();

class ViewType {
    int VIEW_PROGRESS = 1;
    int VIEW_NO_DATA = 2;
    int VIEW_RESTAURANT = 3;
    int VIEW_CUISINE = 4;
    int VIEW_INFO = 6;
}

private ViewType mViewType = new ViewType();

private Context mContext;

private int mCuisineItem = 1;
private int mInfoItem = 1;
private int mShowNoItem = 0;

private boolean mIsLoading;
private int mRestaurantNumber;
private int mCurrentPage;

private List<Data> mDataList;
private List<CuisineData> mCuisines;

private PaginationListener mPaginationListener;
private HorizontalPaginationListener mHorizontalPaginationListener;
private SearchResultClickListener mSearchResultClickListener;

private String mFrom;

public HomeAdapter(Context context, List<Data> dataList, List<CuisineData> cuisines, RecyclerView recyclerView, SearchResultClickListener searchResultClickListener) {
    mContext = context;
    mDataList = dataList;
    mCuisines = cuisines;
    mSearchResultClickListener = searchResultClickListener;

    if (recyclerView.getLayoutManager() instanceof LinearLayoutManager) {

        final LinearLayoutManager llManager = (LinearLayoutManager) recyclerView.getLayoutManager();

        recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
            @Override
            public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
                super.onScrolled(recyclerView, dx, dy);

                int visible_threshold = 1;
                int total_item_count = llManager.getItemCount();
                int last_visible_item = llManager.findLastVisibleItemPosition();

                if (!mIsLoading && total_item_count <= (last_visible_item + visible_threshold)) {
                    if (mPaginationListener != null) mPaginationListener.onPagination();
                    mIsLoading = true;
                }
            }
        });
    }
}

public void setmPaginationListener(PaginationListener paginationListener) {
    mPaginationListener = paginationListener;
}

public void setmHorizontalPaginationListener(HorizontalPaginationListener horizontalPaginationListener) {
    mHorizontalPaginationListener = horizontalPaginationListener;
}

public void setLoaded() {
    mIsLoading = false;
}

public void setmRestaurantNumber(int restaurantNumber) {
    mRestaurantNumber = restaurantNumber;
}

public void setmCurrentPage(int currentPage) {
    mCurrentPage = currentPage;
}

public void addCuisine(String from) {
    mFrom = from;
    notifyDataSetChanged();
}

public void addCuisines(List<CuisineData> cuisines, String from) {
    mFrom = from;
    mCuisines.clear();
    mCuisines = cuisines;
    notifyDataSetChanged();
}

public void addRestaurants(List<Data> dataList) {
    mShowNoItem = 0;
    if(mCurrentPage == 1) notifyItemChanged(1);
    if (mCurrentPage == 1) notifyItemChanged(2);
    int insert_index = mDataList.size();
    int pos_start = insert_index + mCuisineItem + mInfoItem;
    mDataList.addAll(insert_index, dataList);
    notifyItemRangeInserted(pos_start, dataList.size());
}

public void removeRestaurants() {
    mShowNoItem = 1;
    mDataList.clear();
    mDataList = new ArrayList<>();
    notifyItemRangeRemoved(mCuisineItem + mInfoItem, mDataList.size());
    notifyItemChanged(2);
}

public void addProgressBar(Data data) {
    mDataList.add(data);
    notifyItemInserted(getItemCount() - 1);
}

public void removeProgressBar() {
    if (mDataList.size() > 0) {
        mDataList.remove(mDataList.size() - 1);
        notifyItemRemoved(mCuisineItem + mInfoItem + mDataList.size());
    }
}

public void removeAll() {
    mDataList.clear();
    mCuisines.clear();
    mShowNoItem = 0;
    notifyDataSetChanged();
}

@Override
public int getItemCount() {
    return mDataList.size() + mShowNoItem + mCuisineItem + mInfoItem;
}

@Override
public int getItemViewType(int position) {
    if (position == 0) return mViewType.VIEW_CUISINE;
    if (position == 1) return mViewType.VIEW_INFO;
    return mShowNoItem == 0 ? (mDataList.get(position - (mCuisineItem + mInfoItem)) != null ? mViewType.VIEW_RESTAURANT : mViewType.VIEW_PROGRESS)
            : mViewType.VIEW_NO_DATA;
}

@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    if (viewType == mViewType.VIEW_CUISINE) {
        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_horizontal_cuisines, parent, false);
        return new ViewHolderCuisinesList(mContext, view, mHorizontalPaginationListener);
    }

    if (viewType == mViewType.VIEW_INFO) {
        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_restaurant_number, parent, false);
        return new ViewHolderRestaurantNumber(mContext, view);
    }

    if (mShowNoItem == 0) {
        if (viewType == mViewType.VIEW_RESTAURANT) {
            View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.food_item_nearest_restaurant, parent, false);
            return new ViewHolderRestaurant(mContext, view, mSearchResultClickListener);
        } else if (viewType == mViewType.VIEW_PROGRESS) {
            View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_progress, parent, false);
            return new ViewHolderProgress(view);
        }
    } else {
        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_empty, parent, false);
        return new ViewHolderEmpty(view);
    }

    return null;
}

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

    if (holder instanceof ViewHolderSearch) {
        ((ViewHolderSearch) holder).onBind();
    }

    if (holder instanceof ViewHolderCuisinesList) {
        if (!TextUtils.isEmpty(mFrom)) {
            if (mFrom.equalsIgnoreCase(AppConstants.CUISINES))
                ((ViewHolderCuisinesList) holder).onBind(mCuisines);
            else if (mFrom.equalsIgnoreCase(AppConstants.CUISINE))
                ((ViewHolderCuisinesList) holder).onBind_();
        }
    }

    if (holder instanceof ViewHolderRestaurantNumber) {
        ((ViewHolderRestaurantNumber) holder).onBind(mRestaurantNumber);
    }

    if (mShowNoItem == 0) {
        if (holder instanceof ViewHolderRestaurant) {
            ((ViewHolderRestaurant) holder).onBind(position - (mCuisineItem + mInfoItem), mDataList.get(position - (mCuisineItem + mInfoItem)));
        } else if (holder instanceof ViewHolderProgress) {
            ((ViewHolderProgress) holder).onBind();
        }
    } else {
        if (holder instanceof ViewHolderEmpty) {
            ((ViewHolderEmpty) holder).onBind(mContext.getString(R.string.no_result_found));
        }
    }
}

}