为什么我的 Android 动态功能模块的视图没有 id?



在动态功能模块中对"活动"布局进行充气时,我看到以下崩溃:

Caused by: java.lang.IllegalStateException: FragmentContainerView must have an android:id to add Fragment com.example.MyFragment
at androidx.fragment.app.FragmentContainerView.<init>(FragmentContainerView.java:171)

FragmentContainerView XML确实具有android:id属性:

<androidx.fragment.app.FragmentContainerView
android:id="@+id/fragment_host_view"
android:name="com.example.MyFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.0" />

启动流程如下:Base App Module的MainActivity安装动态功能模块->当功能模块安装完成时,基本应用程序模块的MainActivity对名为FeatureActivity的功能模块内的Activity调用startActivity((->功能模块的FeatureActivity.onCreate((尝试使用R.layout.activity_Feature设置ContentView((->activity_feature布局XML(仅存在于功能模块中(由于FragmentContainerView引发的IllegalStateException而引发膨胀异常,如上所述。

文档中提到了与跨越功能模块边界访问资源和资产有关的恶作剧,但我认为这不适用于我的情况,因为有问题的资源id(fragment_host_view(只能由功能模块的一部分FeatureActivity访问。我有我的主模块的应用程序调用SplitCompat.install((,MainActivity和FeatureActivity都按照文档执行SplitCompaat.installActivity((,但这似乎无关紧要。

查看引用的FragmentContainerView源代码表明,根本问题是我的FragmentContainerView在动态功能安装流程中不知何故从XML中丢失了其视图id;如果我将动态功能模块转换为库模块,则不会发生此错误。

我的FragmentContainerView来自androidx.fragment:fragment-ktx:1.3.6,我正在根据本地测试文档使用bundletool进行测试。

为什么我的FragmentContainerView在动态功能安装后在运行时膨胀时没有id?

这是FragmentContainerView中的一个错误https://issuetracker.google.com/issues/213086140?pli=1这是由于假设有效的视图ID在从十六进制转换为32位有符号整数时将具有正值而导致的,但情况并非总是如此。IIRC,视图ID是从32位十六进制范围的高位字节分配的,作为动态功能模块的一部分,似乎会显著增加分配的ID值,因此在转换为带符号的32位整数格式时会进入溢出范围,从而创建有效的负视图ID。旧的FragmentContainerView正在查找ID>0,所以否定的视图ID将失败,结果就是我上面问题中的错误。

此错误已在Fragment模块v1.4.1 中修复

<androidx.fragment.app.FragmentContainerView
android:id="@+id/fragment_host_view"
android:name="com.example.MyFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.0" />

<fragment
android:id="@+id/fragment_host_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.0" />

最新更新