给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);
}
}
}
本文深入探讨了使用RecyclerView与HeaderAndFooterWrapper进行局部刷新时遇到的问题及解决方案。详细讲解了为何HeaderAndFooterWrapper的onBindViewHolder三参数方法未被调用,并提供了解决方案,通过自定义实现使局部刷新功能得以正常工作。

1329

被折叠的 条评论
为什么被折叠?



