use*_*123 5 android android-recyclerview android-concatadapter
我有一个 RecyclerView 适配器,它可以处理我多年来一直使用的几种视图类型。最近,我发现了ConcatAdapter,但我似乎遇到了一个问题,它似乎返回了错误的值getItemViewType()。
我有一个用例,我想显示标题及其下方的项目列表。我已经为标题创建了一个新的适配器类,但列表项将继续使用我的旧适配器(它还处理其他几种视图类型)。
所以我连接了两个适配器:
HeaderAdapter headerAdapter = new HeaderAdapter(context);
PostAdapter postAdapter = new PostAdapter(context, postData);
ConcatAdapter concatAdapter = new ConcatAdapter(headerAdapter, postAdapter);
recyclerView.setAdapter(concatAdapter);
Run Code Online (Sandbox Code Playgroud)
这工作正常,但是当我打开活动时,它立即崩溃并给出错误:
java.lang.ClassCastException:com.myapp.android.adapter.PostAdapter$PostViewHolder 无法转换为 com.myapp.android.adapter.PostAdapter$FooterViewHolder
这是没有意义的,因为我什至从未在回收器视图中添加页脚。
我的getItemViewType()方法PostAdapter看起来像这样:
@Override
public int getItemViewType(int position) {
if (data.get(position) instanceof Footer) {
return TYPE_FOOTER;
} else if (data.get(position) instanceof Post) {
return TYPE_POST;
}
return -1;
}
Run Code Online (Sandbox Code Playgroud)
我的onBindViewHolder()看起来像这样:
@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
switch (holder.getItemViewType()) {
case TYPE_FOOTER:
FooterViewHolder vh1 = (FooterViewHolder) holder;
configureFooterViewHolder(vh1, position);
break;
case TYPE_POST:
PostViewHolder vh2 = (PostViewHolder) holder;
configurePostViewHolder(vh2, position);
break;
default:
break;
}
}
Run Code Online (Sandbox Code Playgroud)
但无论出于何种原因,当我运行调试器时,它都会落在行上FooterViewHolder vh1 = (FooterViewHolder) holder;,即使我从未将页脚作为PostAdapter数据的一部分包含在内。
那么它为什么会落到这个地步呢?为什么 ConcatAdapter 会在处理多种视图类型的适配器中导致如此奇怪的行为?
当您绑定视图持有者时,您应该使用RecyclerView.Adapters.getItemViewType(position),而不是RecyclerView.ViewHolder.getItemViewType():
@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
switch (getItemViewType(position)) { // not holder.getItemViewType()
case TYPE_FOOTER:
FooterViewHolder vh1 = (FooterViewHolder) holder;
configureFooterViewHolder(vh1, position);
break;
case TYPE_POST:
PostViewHolder vh2 = (PostViewHolder) holder;
configurePostViewHolder(vh2, position);
break;
default:
break;
}
}
Run Code Online (Sandbox Code Playgroud)
您收到错误,因为视图持有者已被回收,它可能是任何视图持有者,因此ClassCastException当您强制将其强制转换为错误的类时,它会抛出错误。
看来是故意的。经过一番调试后,我发现adapter.getItemViewType(localPosition)这一行是正确的,但是 ConcatAdapter 还做了一个额外的“从本地到全局项目视图类型的转换”,我从未配置过,但至少它覆盖了我最初想要的做。
因此,您根本看不到本地项目视图类型值,您只是从 ConcatAdapter 获取一些随机分配的索引。由于所有这些都是私人的,因此您唯一的选择就是反思。
祝你好运。
(好吧,对于一个真正的答案,您还可以启用ConcatAdapter.Config(isolateViewTypes = false),确保所有项目视图类型彼此不同,它们实际上是不同的,而不是仅仅返回0左右return super.getItemViewType(position),然后getItemViewType不会创建local -> global映射以确保跨项目的一致性适配器,而是它会为您返回本地项目视图类型)
val concatAdapter = ConcatAdapter(
ConcatAdapter.Config.Builder()
.setIsolateViewTypes(false)
.build(),
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
3655 次 |
| 最近记录: |