给RecyclerView添加头布局使用的是HeaderAndFooterWrapper,然后我做的是列表滑动播放短视频,但是在每个视频Item的下面都有拔草按钮跟数字,点击种草或者拔草要刷新数字。使用RecyclerView的局部刷新即
headerAndFooterWrapper.notifyItemChanged(zhong_ba_cao_pos+1,"test");
然后build发现点击后数字没变化,以为代码哪里错了然后一路debug发现确实执行完方法了,只不过是没调用起 HeaderAndFooterWrapper包含的实际列表适配器即
mInnerAdapter中的onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position, @NonNull List<Object> payloads)
然后开始度娘ing(怎么没调用到onBindViewHolder的三个参数函数?)
千篇一律的都是说在适配器的onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position, @NonNull List<Object> payloads)中判断payloads为空如何如何,但是这个我已经在mInnerAdapter的onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position, @NonNull List<Object> payloads)写了;
os:what鬼?
然后自己写了个简单的RecyclerView局部刷新的demo 运行发现是可以刷新局部item的,说明代码没有问题,然后把RecyclerView的adapter从headerAndFooterWrapper变成不加头布局的mInnerAdapter,一步一步缩小问题范围,改完后发现局部也是可以刷新的,看来问题就出在这个头布局适配器即HeaderAndFooterWrapper上。
在HeaderAndFooterWrapper文件中发现了同样的构造
onBindViewHolder(RecyclerView.ViewHolder holder, int position)但是没有三参的,灵机一动,自己加了个即
@Override public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position, @NonNull List<Object> payloads) { if(payloads.isEmpty()){ onBindViewHolder(holder,position); }else{ mInnerAdapter.onBindViewHolder(holder,position - getHeadersCount(),payloads); } }
运行后发现ok了,问题解决。折腾了下午好一会,记录一下。附上HeaderAndFooterWrapper的代码跟mInnerAdapter的代码如下,只看二个适配器中的onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position, @NonNull List<Object> payloads)函数就行了:
public class HeaderAndFooterWrapper extends RecyclerView.Adapter<RecyclerView.ViewHolder>{ public static final int BASE_ITEM_TYPE_HEADER = 100000; public static final int BASE_ITEM_TYPE_FOOTER = 200000; private SparseArrayCompat<View> mHeaderViews = new SparseArrayCompat<>(); private SparseArrayCompat<View> mFooterViews = new SparseArrayCompat<>(); private RecyclerView.Adapter mInnerAdapter; public HeaderAndFooterWrapper(RecyclerView.Adapter innerAdapter) { mInnerAdapter = innerAdapter; } @Override public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { if (mHeaderViews.get(viewType) != null){ return new MyViewHolder(mHeaderViews.get(viewType)); }else if (mFooterViews.get(viewType) != null){ return new MyViewHolder(mFooterViews.get(viewType)); } return mInnerAdapter.onCreateViewHolder(parent,viewType); } @Override public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position, @NonNull List<Object> payloads) { if(payloads.isEmpty()){ onBindViewHolder(holder,position); }else{ mInnerAdapter.onBindViewHolder(holder,position - getHeadersCount(),payloads); } } @Override public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { if (isHeaderViewPos(position)) return; if (isFooterViewPos(position)) return; mInnerAdapter.onBindViewHolder(holder,position - getHeadersCount()); } @Override public int getItemCount() { return getHeadersCount() + getFootersCount() + getRealItemCount(); } @Override public int getItemViewType(int position) { if (isHeaderViewPos(position)){ return mHeaderViews.keyAt(position); }else if (isFooterViewPos(position)){ return mFooterViews.keyAt(position - getHeadersCount() - getRealItemCount()); } return mInnerAdapter.getItemViewType(position - getHeadersCount()); } /** * 获取正常数据的size * @return */ private int getRealItemCount(){ return mInnerAdapter.getItemCount(); } /** * 判断是否是Header * @param position * @return */ private boolean isHeaderViewPos(int position){ return position < getHeadersCount(); } /** * 判断是否是Footer * @param position * @return */ private boolean isFooterViewPos(int position){ return position >= getHeadersCount() + getRealItemCount(); } public void addHeaderView(View view){ mHeaderViews.put(mHeaderViews.size() + BASE_ITEM_TYPE_HEADER,view); } public void addFooterView(View view){ mFooterViews.put(mFooterViews.size() + BASE_ITEM_TYPE_FOOTER,view); } private int getHeadersCount(){ return mHeaderViews.size(); } public int getFootersCount(){ return mFooterViews.size(); } class MyViewHolder extends RecyclerView.ViewHolder{ public MyViewHolder(View itemView) { super(itemView); } } /** * 适配网格布局 * @param recyclerView */ @Override public void onAttachedToRecyclerView(RecyclerView recyclerView) { mInnerAdapter.onAttachedToRecyclerView(recyclerView); final RecyclerView.LayoutManager layoutManager = recyclerView.getLayoutManager(); if (layoutManager instanceof GridLayoutManager){ final GridLayoutManager gridLayoutManager = (GridLayoutManager) layoutManager; gridLayoutManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() { @Override public int getSpanSize(int position) { return isHeaderViewPos(position) || isFooterViewPos(position) ? ((GridLayoutManager) layoutManager).getSpanCount() : 1; } }); } } @Override public void onViewAttachedToWindow(RecyclerView.ViewHolder holder) { mInnerAdapter.onViewAttachedToWindow(holder); int position = holder.getLayoutPosition(); if (isHeaderViewPos(position)||isFooterViewPos(position)){ ViewGroup.LayoutParams lp = holder.itemView.getLayoutParams(); if (lp != null && lp instanceof StaggeredGridLayoutManager.LayoutParams){ StaggeredGridLayoutManager.LayoutParams p = (StaggeredGridLayoutManager.LayoutParams) lp; p.setFullSpan(true); } } } }
public class AdapterRecyclerView extends RecyclerView.Adapter<AdapterRecyclerView.MyViewHolder> { public static final String TAG = "AdapterRecyclerView"; private Context context; private MyData videoData; public AdapterRecyclerView(Context context, MyData videoData) { this.context = context; this.videoData = videoData; } @Override public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { MyViewHolder holder = new MyViewHolder(LayoutInflater.from( context).inflate(R.layout.item_videoview, parent, false)); return holder; } @Override public void onBindViewHolder(@NonNull MyViewHolder holder, int position, @NonNull List<Object> payloads) { if(payloads.isEmpty()){ onBindViewHolder(holder,position); }else{ MyRow rowItem = videoData.get(position); if (MathUtils.getInt(rowItem.get("user_like_flag") + "") == 1) { //like_main_bottom holder.tv_font_zhong_cao.setTextColor(context.getResources().getColor(R.color.my_red)); } else { holder.tv_font_zhong_cao.setTextColor(context.getResources().getColor(R.color.gray_color_d9d9d9)); } if (MathUtils.getInt(rowItem.get("user_dislike_flag") + "") == 1) { //like_main_bottom holder.tv_font_ba_cao.setTextColor(context.getResources().getColor(R.color.my_red)); } else { holder.tv_font_ba_cao.setTextColor(context.getResources().getColor(R.color.gray_color_d9d9d9)); } holder.zhong_cao_num.setText(MathUtils.getInt(rowItem.get("like_count") + "") + ""); holder.ba_cao_num.setText(MathUtils.getInt(rowItem.get("dislike_count") + "") + ""); } } @SuppressLint("LongLogTag") @Override public void onBindViewHolder(MyViewHolder holder, int position) { //里面是我的业务逻辑 不用管 MyRow rowItem = videoData.get(position); holder.userAvatar.setTag(null); Glide.with(context.getApplicationContext()).asBitmap().load((rowItem.getString("avatar_url"))).into(holder.userAvatar); holder.userAvatar.setTag(rowItem.getInt("user_id")); Log.i(TAG, "onBindViewHolder [" + holder.jzvdStd.hashCode() + "] position=" + position); holder.jzvdStd.setUp( videoData.get(position).getString("play_addr"), "", Jzvd.SCREEN_FULLSCREEN); Glide.with(holder.jzvdStd.getContext()).load( videoData.get(position).getString("cover_url")).into(holder.jzvdStd.posterImageView); LinearLayout.LayoutParams lps = (LinearLayout.LayoutParams) holder.layout_card.getLayoutParams(); lps.width = ScreenUtils.getScreenWidth(context)-ScreenUtils.dp2px(context,10); lps.height = (int) (lps.width/0.727); holder.layout_card.setLayoutParams(lps); holder.layout_card.setRadius(5f); holder.video_des.setText(rowItem.getString("video_des")); if(rowItem.getBoolean("isShowLink")){ holder.ll_shop_tab.setVisibility(View.VISIBLE); }else{ holder.ll_shop_tab.setVisibility(View.GONE); } MyRow r = new MyRow(); r.put("goods_from",rowItem.getString("goods_from")); r.put("goods_url",rowItem.getString("goods_url")); holder.fest_buy.setTag(r); MyRow rCao = new MyRow(); rCao.put("id",rowItem.getInt("id")); rCao.put("pos",position); rCao.put("like_count",MathUtils.getInt(rowItem.get("like_count")+"")); rCao.put("dislike_count",MathUtils.getInt(rowItem.get("dislike_count")+"")); rCao.put("user_like_flag",MathUtils.getInt(rowItem.get("user_like_flag")+"")); rCao.put("user_dislike_flag",MathUtils.getInt(rowItem.get("user_dislike_flag")+"")); holder.ll_comment.setTag(rCao); holder.zhong_cao.setTag(rCao); holder.ba_cao.setTag(rCao); holder.img_follow.setTag(rowItem.getInt("user_id")); holder.user_name.setText(rowItem.getString("user_nickname")); holder.layout_card.setRadius(5); holder.ll_jubao.setTag(rowItem.getInt("id")); MyRow r1 = new MyRow(); r1.put("pos", position); r1.put("goods_from", rowItem.getString("goods_from")); r1.put("goods_url", rowItem.getString("goods_url")); holder.ll_get_link.setTag(r1); rowItem.put("pos", position); Glide.with(context.getApplicationContext()).asBitmap().load((rowItem.getString("goods_pic"))).into(holder.shop_img); holder.shop_name.setText(rowItem.getString("goods_name")); holder.shop_price.setText("¥"+rowItem.getString("goods_price")); } @Override public int getItemCount() { return null == videoData ? 0 : videoData.size(); } static class MyViewHolder extends RecyclerView.ViewHolder { JzvdStd jzvdStd; CardView layout_card; public CircleImageView userAvatar; public ImageView img_follow; public XCRoundRectImageView shop_img; public TextView name,tv_font_zhong_cao,user_name, tv_font_ba_cao, tv_font_comment, video_des, zhong_cao_num, ba_cao_num, tv_font_sandian, comment_num, shop_name, shop_price, fest_buy; public LinearLayout ll_get_link, ll_jubao, ll_shop_tab,zhong_cao,ba_cao,ll_comment; public MyViewHolder(View itemView) { super(itemView); jzvdStd = itemView.findViewById(R.id.videoplayer); layout_card= itemView.findViewById(R.id.layout_card); // name = (TextView) itemView.findViewById(R.id.tv_video_name); ll_get_link = itemView.findViewById(R.id.ll_get_link); userAvatar = (CircleImageView) itemView.findViewById(R.id.head_icon); img_follow = (ImageView) itemView.findViewById(R.id.img_follow); tv_font_zhong_cao = itemView.findViewById(R.id.tv_font_zhong_cao); tv_font_ba_cao = itemView.findViewById(R.id.tv_font_ba_cao); // tv_font_get_link = itemView.findViewById(R.id.tv_font_get_link); tv_font_comment = itemView.findViewById(R.id.tv_font_comment); tv_font_sandian = itemView.findViewById(R.id.tv_font_sandian); video_des = itemView.findViewById(R.id.video_des); zhong_cao_num = itemView.findViewById(R.id.zhong_cao_num); ba_cao_num = itemView.findViewById(R.id.ba_cao_num); comment_num = itemView.findViewById(R.id.comment_num); ll_jubao = itemView.findViewById(R.id.ll_jubao); ll_shop_tab = itemView.findViewById(R.id.ll_shop_tab); shop_name = (TextView) itemView.findViewById(R.id.shop_name); shop_price = (TextView) itemView.findViewById(R.id.shop_price); shop_img = itemView.findViewById(R.id.shop_img); fest_buy = itemView.findViewById(R.id.fest_buy); zhong_cao = itemView.findViewById(R.id.zhong_cao); ba_cao= itemView.findViewById(R.id.ba_cao); user_name = itemView.findViewById(R.id.user_name); ll_comment= itemView.findViewById(R.id.ll_comment); } } }