RecyclerView.Adapter 大量滚动时出现 ClassCastException
RecyclerView.Adapter ClassCastException when scrolling a lot
我正在构建一个聊天应用程序,我在其中使用带适配器的 RecyclerView 并且它使用不同的查看器,因为服务器发送需要不同视图图表等的富内容
当我正常使用应用程序并与服务器聊天时,要求不同的内容,这意味着不同的观众一切正常。每次我发送不同的请求时,顶级适配器都会将主视窗转换为我需要的视窗。
经过长时间的聊天和不同的 viewholders 生成和膨胀后,如果我快速滚动 RecyclerView,上下滚动,主适配器正在重新呈现项目并且它会因 classcastException 而崩溃,如果更早的话,聊天的时候没有崩溃
这是一个例子:
@NonNull
@Override
public ViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int viewType) {
LayoutInflater inflater = LayoutInflater.from(viewGroup.getContext());
//depending the type of rich content i get from the server i inflate the respective xml
switch (MessageType.values()[viewType]) {
case 1:
View plainTextView = inflater....
return new ViewHolder1(plainTextView);
case 2:
View secondView = inflater...
return new ViewHolder2(secondView);
case 3:
View thirdView = inflater...
return new ViewHolder3(verticalView);
}
return null;
}
然后在 onBindViewHolder 中,我根据 onCreateViewHolder 的情况转换 ViewHolder
@Override
public void onBindViewHolder(@NonNull ViewHolder holder, final int position) {
[...]
case 2:
final ViewHolder2 holder = (ViewHolder2) holder;
//do stuff
break;
错误
2020-01-20 13:22:57.322 E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.----.app, PID: 28353
java.lang.ClassCastException: com.-----.ui.adapters.MainCarouselAdapter$CarouselViewHolder cannot be cast to com.----.ui.adapters.QuickRepliesAdapter$OptionsViewHolder
at com.-----.ui.adapters.QuickRepliesAdapter.onBindViewHolder(QuickRepliesAdapter.java:22)
at androidx.recyclerview.widget.RecyclerView$Adapter.onBindViewHolder(RecyclerView.java:7065)
at androidx.recyclerview.widget.RecyclerView$Adapter.bindViewHolder(RecyclerView.java:7107)
at androidx.recyclerview.widget.RecyclerView$Recycler.tryBindViewHolderByDeadline(RecyclerView.java:6012)
at androidx.recyclerview.widget.RecyclerView$Recycler.tryGetViewHolderForPositionByDeadline(RecyclerView.java:6279)
at androidx.recyclerview.widget.GapWorker.prefetchPositionWithDeadline(GapWorker.java:288)
at androidx.recyclerview.widget.GapWorker.prefetchInnerRecyclerViewWithDeadline(GapWorker.java:335)
at androidx.recyclerview.widget.GapWorker.flushTaskWithDeadline(GapWorker.java:351)
at androidx.recyclerview.widget.GapWorker.flushTasksWithDeadline(GapWorker.java:361)
at androidx.recyclerview.widget.GapWorker.prefetch(GapWorker.java:368)
at androidx.recyclerview.widget.GapWorker.run(GapWorker.java:399)
at android.os.Handler.handleCallback(Handler.java:907)
at android.os.Handler.dispatchMessage(Handler.java:105)
at android.os.Looper.loop(Looper.java:216)
at android.app.ActivityThread.main(ActivityThread.java:7625)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:524)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:987)
对于遇到类似问题的任何人,我的主 RecyclerView 和子 RecyclerView 有一个共享的 viewPool。
Recycled view pools allow multiple RecyclerViews to share a common pool of scrape views. This can be useful if you have multiple RecyclerViews with adapters that use the same view types, for example if you have several data sets with the same kinds of item views displayed by a ViewPager.
我的通货膨胀中没有相同的 ViewType,所以我发现它必须离开。
删除它时,该错误不再存在。此外,我在不同的 xml 文件中修复了我的“命名”,这些文件根据将要调用的 ViewHolder 而膨胀。我对一些常见的 TextView 等使用了相同的名称。
我正在构建一个聊天应用程序,我在其中使用带适配器的 RecyclerView 并且它使用不同的查看器,因为服务器发送需要不同视图图表等的富内容
当我正常使用应用程序并与服务器聊天时,要求不同的内容,这意味着不同的观众一切正常。每次我发送不同的请求时,顶级适配器都会将主视窗转换为我需要的视窗。
经过长时间的聊天和不同的 viewholders 生成和膨胀后,如果我快速滚动 RecyclerView,上下滚动,主适配器正在重新呈现项目并且它会因 classcastException 而崩溃,如果更早的话,聊天的时候没有崩溃
这是一个例子:
@NonNull
@Override
public ViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int viewType) {
LayoutInflater inflater = LayoutInflater.from(viewGroup.getContext());
//depending the type of rich content i get from the server i inflate the respective xml
switch (MessageType.values()[viewType]) {
case 1:
View plainTextView = inflater....
return new ViewHolder1(plainTextView);
case 2:
View secondView = inflater...
return new ViewHolder2(secondView);
case 3:
View thirdView = inflater...
return new ViewHolder3(verticalView);
}
return null;
}
然后在 onBindViewHolder 中,我根据 onCreateViewHolder 的情况转换 ViewHolder
@Override
public void onBindViewHolder(@NonNull ViewHolder holder, final int position) {
[...]
case 2:
final ViewHolder2 holder = (ViewHolder2) holder;
//do stuff
break;
错误
2020-01-20 13:22:57.322 E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.----.app, PID: 28353
java.lang.ClassCastException: com.-----.ui.adapters.MainCarouselAdapter$CarouselViewHolder cannot be cast to com.----.ui.adapters.QuickRepliesAdapter$OptionsViewHolder
at com.-----.ui.adapters.QuickRepliesAdapter.onBindViewHolder(QuickRepliesAdapter.java:22)
at androidx.recyclerview.widget.RecyclerView$Adapter.onBindViewHolder(RecyclerView.java:7065)
at androidx.recyclerview.widget.RecyclerView$Adapter.bindViewHolder(RecyclerView.java:7107)
at androidx.recyclerview.widget.RecyclerView$Recycler.tryBindViewHolderByDeadline(RecyclerView.java:6012)
at androidx.recyclerview.widget.RecyclerView$Recycler.tryGetViewHolderForPositionByDeadline(RecyclerView.java:6279)
at androidx.recyclerview.widget.GapWorker.prefetchPositionWithDeadline(GapWorker.java:288)
at androidx.recyclerview.widget.GapWorker.prefetchInnerRecyclerViewWithDeadline(GapWorker.java:335)
at androidx.recyclerview.widget.GapWorker.flushTaskWithDeadline(GapWorker.java:351)
at androidx.recyclerview.widget.GapWorker.flushTasksWithDeadline(GapWorker.java:361)
at androidx.recyclerview.widget.GapWorker.prefetch(GapWorker.java:368)
at androidx.recyclerview.widget.GapWorker.run(GapWorker.java:399)
at android.os.Handler.handleCallback(Handler.java:907)
at android.os.Handler.dispatchMessage(Handler.java:105)
at android.os.Looper.loop(Looper.java:216)
at android.app.ActivityThread.main(ActivityThread.java:7625)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:524)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:987)
对于遇到类似问题的任何人,我的主 RecyclerView 和子 RecyclerView 有一个共享的 viewPool。
Recycled view pools allow multiple RecyclerViews to share a common pool of scrape views. This can be useful if you have multiple RecyclerViews with adapters that use the same view types, for example if you have several data sets with the same kinds of item views displayed by a ViewPager.
我的通货膨胀中没有相同的 ViewType,所以我发现它必须离开。
删除它时,该错误不再存在。此外,我在不同的 xml 文件中修复了我的“命名”,这些文件根据将要调用的 ViewHolder 而膨胀。我对一些常见的 TextView 等使用了相同的名称。