关于RecyclerView.Adapter 的 onBindViewHolder 混合布局 不执行的问题
最近在一个现有Adapter中 添加了多种混合布局样式,结果运行发现,新增的混合布局所在的item 不会去执行 onBindViewHolder(@NotNull RecyclerView.ViewHolder holder, int position) 纳闷啊,不应该啊,这怎么能有问题?起初,以为是混合布局中嵌套的RecyclerView的问题,换成只有一个TextView的标题布局也一样,首次加载列表就不执行。此时实在不知道是哪里的问题了,看了之前同样使用混合布局的其他Adapter,都正常,哪里有问题呢?怀疑人生了…… 这种时候,借助一下万能的百度吧,查询到的结果,都是 什么没有设置setLayoutManager 类似这种,我的明显不属于这种情况。
突然脑子灵光闪现,这个方法 onBindViewHolder(@NotNull RecyclerView.ViewHolder holder, int position) 由谁触发的,查看源码,才能找到根本原因。果然,很快找到了答案,对比自己的代码,
确实是这个问题,修改后一切正常!!废话说多了,以下由源码引入:
//暂时称之为【方法一】
public abstract void onBindViewHolder(@NonNull VH var1, int var2); //该方法是抽象的,其是由下述三个参数的重载方法调用的.
//【方法二】
public void onBindViewHolder(@NonNull VH holder, int position, @NonNull List<Object> payloads) {
this.onBindViewHolder(holder, position); //此处真正的触发位置.
}
由上,显而易见,若出现【方法一】没有执行的问题,是不是自己的代码重写了【方法二】,并在【方法二】中的逻辑书写有问题。一般重写【方法二】都是存在局部刷新item的
需求,默认不会去重写。但是重写时需要注意,尤其是混合布局时。以下为修改前的原始代码:
突然脑子灵光闪现,这个方法 onBindViewHolder(@NotNull RecyclerView.ViewHolder holder, int position) 由谁触发的,查看源码,才能找到根本原因。果然,很快找到了答案,对比自己的代码,
确实是这个问题,修改后一切正常!!废话说多了,以下由源码引入:
//暂时称之为【方法一】
public abstract void onBindViewHolder(@NonNull VH var1, int var2); //该方法是抽象的,其是由下述三个参数的重载方法调用的.
//【方法二】
public void onBindViewHolder(@NonNull VH holder, int position, @NonNull List<Object> payloads) {
this.onBindViewHolder(holder, position); //此处真正的触发位置.
}
由上,显而易见,若出现【方法一】没有执行的问题,是不是自己的代码重写了【方法二】,并在【方法二】中的逻辑书写有问题。一般重写【方法二】都是存在局部刷新item的
需求,默认不会去重写。但是重写时需要注意,尤其是混合布局时。以下为修改前的原始代码:
@Override public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position, @NonNull List payloads) { if (holder instanceof ContentViewHolder) { if (payloads.isEmpty()) { //错误的位置 onBindViewHolder(holder, position); }else{ //执行局部更新的操作.. } } }
很明显,上述代码存在逻辑问题,当然,添加混合布局前,上述代码也没啥问题,因为只有ContentViewHolder 这一种布局,这不是一个好的习惯!回到本文开始,由于需求的变更,现在我加入了混合布局,此时,新增了CardViewHolder,但是可以发现public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position, @NonNull List payloads) 的逻辑中没有相关的处理,默认payloads.isEmpty() 为空,但是该条件放在了holder instanceof ContentViewHolder内部,导致其他布局均无法触发onBindViewHolder(holder, position); 这就是文章开始遇到的问题。修改起来也很简单,如下:
@Override public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position, @NonNull List payloads) { if (payloads.isEmpty()) {//正常执行流程. onBindViewHolder(holder, position); }else { //根据需要,进行相应的局部更新处理. if (holder instanceof ContentViewHolder) { } else if(holder instanceof CardViewHolder){ } else if(...){ } }
可以看到,该问题修改起来很简单,问题也很简单,但是明白前,就是摸不着头绪,严格来讲,这属于一个开发中自己挖的坑,由于代码的逻辑问题,或者说是对于onBindViewHolder理解的不透彻导致的问题。所以很多时候不要一知半解,没事儿多看看源码,或者出现问题了,优先查看源码,明白代码的执行流程,知其然更要知其所以然!这次算是一个教训吧,与大家共勉!!