android - ViewHolder 视图创建时没有附加,但是有错误
问题描述
我从 Firebase Crashlytics 收到了一个错误:
Fatal Exception: java.lang.IllegalStateException: ViewHolder views must not be attached when created. Ensure that you are not passing 'true' to the attachToRoot parameter of LayoutInflater.inflate(..., boolean attachToRoot)
at androidx.recyclerview.widget.RecyclerView$Adapter.createViewHolder(RecyclerView.java:7080)
at androidx.recyclerview.widget.RecyclerView$Recycler.tryGetViewHolderForPositionByDeadline(RecyclerView.java:6235)
at androidx.recyclerview.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:6118)
at androidx.recyclerview.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:6114)
at androidx.recyclerview.widget.LinearLayoutManager$LayoutState.next(LinearLayoutManager.java:2303)
at androidx.recyclerview.widget.LinearLayoutManager.layoutChunk(LinearLayoutManager.java:1627)
at androidx.recyclerview.widget.LinearLayoutManager.fill(LinearLayoutManager.java:1587)
at androidx.recyclerview.widget.LinearLayoutManager.onLayoutChildren(LinearLayoutManager.java:665)
at androidx.recyclerview.widget.RecyclerView.dispatchLayoutStep2(RecyclerView.java:4134)
at androidx.recyclerview.widget.RecyclerView.dispatchLayout(RecyclerView.java:3851)
at androidx.recyclerview.widget.RecyclerView.onLayout(RecyclerView.java:4404)
at android.view.View.layout(View.java:23750)
at android.view.ViewGroup.layout(ViewGroup.java:7277)
at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1829)
at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1673)
at android.widget.LinearLayout.onLayout(LinearLayout.java:1582)
at android.view.View.layout(View.java:23750)
at android.view.ViewGroup.layout(ViewGroup.java:7277)
at android.widget.FrameLayout.layoutChildren(FrameLayout.java:332)
at android.widget.FrameLayout.onLayout(FrameLayout.java:270)
at android.view.View.layout(View.java:23750)
at android.view.ViewGroup.layout(ViewGroup.java:7277)
at androidx.constraintlayout.widget.ConstraintLayout.onLayout(ConstraintLayout.java:1855)
at android.view.View.layout(View.java:23750)
at android.view.ViewGroup.layout(ViewGroup.java:7277)
at android.widget.FrameLayout.layoutChildren(FrameLayout.java:332)
at android.widget.FrameLayout.onLayout(FrameLayout.java:270)
at android.view.View.layout(View.java:23750)
at android.view.ViewGroup.layout(ViewGroup.java:7277)
at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1829)
at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1673)
at android.widget.LinearLayout.onLayout(LinearLayout.java:1582)
at android.view.View.layout(View.java:23750)
at android.view.ViewGroup.layout(ViewGroup.java:7277)
at android.widget.FrameLayout.layoutChildren(FrameLayout.java:332)
at android.widget.FrameLayout.onLayout(FrameLayout.java:270)
at android.view.View.layout(View.java:23750)
at android.view.ViewGroup.layout(ViewGroup.java:7277)
at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1829)
at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1673)
at android.widget.LinearLayout.onLayout(LinearLayout.java:1582)
at android.view.View.layout(View.java:23750)
at android.view.ViewGroup.layout(ViewGroup.java:7277)
at android.widget.FrameLayout.layoutChildren(FrameLayout.java:332)
at android.widget.FrameLayout.onLayout(FrameLayout.java:270)
at com.android.internal.policy.DecorView.onLayout(DecorView.java:1099)
at android.view.View.layout(View.java:23750)
at android.view.ViewGroup.layout(ViewGroup.java:7277)
at android.view.ViewRootImpl.performLayout(ViewRootImpl.java:3712)
at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:3164)
at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:2225)
at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:9126)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:999)
at android.view.Choreographer.doCallbacks(Choreographer.java:797)
at android.view.Choreographer.doFrame(Choreographer.java:732)
at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:984)
at android.os.Handler.handleCallback(Handler.java:883)
at android.os.Handler.dispatchMessage(Handler.java:100)
at android.os.Looper.loop(Looper.java:237)
at android.app.ActivityThread.main(ActivityThread.java:8167)
at java.lang.reflect.Method.invoke(Method.java)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:496)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1100)
有问题的行是:
android.view.View.layout (View.java:23750)
这是:
public View getRootView() {
if (mAttachInfo != null) {
final View v = mAttachInfo.mRootView;
if (v != null) {
return v;
}
}
View parent = this;
while (parent.mParent != null && parent.mParent instanceof View) {
parent = (View) parent.mParent;
}
return parent;
}
据我了解,这发生在onCreateViewHolder()
. 当我在我的代码中调用这些函数时,我已经仔细检查了 3 次 - 它们都没有参数attachToRoot: true
。
他们来了:
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): DeviceCellHolder {
val inflater = LayoutInflater.from(parent.context)
val v = inflater.inflate(R.layout.item_header, parent, false)
return DeviceCellHolder(v)
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
val inflater = LayoutInflater.from(parent.context)
return deviceHolder?.getViewHolderFor(viewType, inflater, parent)!!
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): NoDeviceListViewHolder {
val inflater = LayoutInflater.from(parent.context)
val v = inflater.inflate(R.layout.item_find_nothing, parent, false)
return NoDeviceListViewHolder(v)
}
我也知道放置null
而不是父级(AlertDialog 除外)是一种不好的做法,但是在我的代码onBindHeader
布局中,inflater 看起来像这样:
val v = LayoutInflater.from(holder.itemView.context).inflate(R.layout.item_chart, null, false)
有什么问题?
谢谢!
升级版:
这是返回所需视图持有者的函数:
open fun getViewHolderFor(
itemType: Int,
inflater: LayoutInflater,
parent: ViewGroup
): MtXXXBodyViewHolder {
return when (itemType) {
ViewHolderType.DeviceDetailsHeader.typeId -> DeviceDetailsHeaderHolder(inflater, parent)
ViewHolderType.LineInfo.typeId -> InfoLineViewHolder(inflater, parent)
ViewHolderType.ItemChart.typeId -> {
val v = inflater.inflate(R.layout.item_chart, parent, false)
ChartViewHolder(v)
}
ViewHolderType.Item3DObject.typeId -> Gyro3DViewHolder(inflater, parent)
ViewHolderType.MT_111.typeId -> Mt111BodyViewHolder(inflater, parent)
else -> InfoLineViewHolder(inflater, parent)
}
}
升级版 [1]:
每个 DeviceHolder 如下所示:
class DeviceDetailsHeaderHolder(inflater: LayoutInflater, parent: ViewGroup) :
MtXXXBodyViewHolder(inflater.inflate(R.layout.item_device_detail_header, parent, false)) {
val tvDeviceTypeName: TextView = v.tvDeviceTypeName
val tvDeviceMac: TextView = v.tvDeviceMac
val ivDeviceImage: ImageView = v.ivDeviceImage
val ibBack: ImageButton = v.btnCloseDetails
}
解决方案
推荐阅读
- r - 通过在 R 中减去两个栅格,我得到了整个栅格的常数
- python - 使用xpath单击iframe内的元素但不起作用
- fortran - gfortran 9.3.1 | SCL | 缺少 findloc 内在?
- r - Fizz Buzz 无法处理多个向量
- sql - 计算每个城市一个类别的支付百分比
- javascript - Javascript:复制数组中的每个字符串值
- java - 如何增加android中OkHttp中请求的超时时间?
- java - 如何在java中连接字段?
- java - “远程确认失败:scp:模糊目标”,同时使用 Windows 机器上的“scp”上传文件,而它在 Linux 和 Mac 上工作
- php - 在 WordPress 中将 +90K 帖子导入自定义帖子类型