使用严格收缩器时,为什么我的应用程序会因 MotionLayout 中的 Resources$NotFoundException 崩溃,如何修复它?

问题描述 投票:0回答:1

我最近在我的 Android 项目中启用了严格收缩器,以积极删除未使用的资源,如官方文档中所述https://developer.android.com/build/shrink-code#strict-reference-checks

但是,启用它后,每当我尝试打开包含 MotionLayout 的屏幕时,我的应用程序就会开始崩溃,并出现以下错误:

Caused by: android.content.res.Resources$NotFoundException: Unable to find resource ID #0x7f0a03f0
    at android.content.res.ResourcesImpl.getResourceTypeName(ResourcesImpl.java:316)
    at androidx.constraintlayout.motion.widget.MotionScene$Transition.fill(MotionScene.java:978)
    at androidx.constraintlayout.motion.widget.MotionScene.load(MotionScene.java:1090)
    at androidx.constraintlayout.motion.widget.MotionLayout.init(MotionLayout.java:3840)
    at androidx.constraintlayout.motion.widget.MotionLayout.<init>(MotionLayout.java:1124)
    at com.mypackage.MyViewBinding.inflate(MyViewBinding.java:102)
    at com.mypackage.MyView.<init>(MyView.kt:37)
android crash android-motionlayout shrinkresources
1个回答
0
投票

发生崩溃的原因是 MotionLayout 依赖反射来处理其过渡和关键帧,这会导致使用严格收缩器时出现问题。具体来说,

MotionLayout
使用反射来初始化其内部
KeyFrames.java
文件中的关键帧:

sKeyMakers.put(KeyAttributes.NAME, KeyAttributes.class.getConstructor())
sKeyMakers.put(KeyPosition.NAME, KeyPosition.class.getConstructor())
sKeyMakers.put(KeyCycle.NAME, KeyCycle.class.getConstructor())
sKeyMakers.put(KeyTimeCycle.NAME, KeyTimeCycle.class.getConstructor())
sKeyMakers.put(KeyTrigger.NAME, KeyTrigger.class.getConstructor())

由于代码中未显式引用这些资源 ID,因此严格收缩器会认为它们未使用并删除它们。当 MotionLayout 尝试在运行时访问这些资源时,这会导致

Resources$NotFoundException

解决方案

为了防止收缩器删除必要的资源 ID,请创建一个 keep.xml 文件并使用 tools:keep 属性指定 MotionLayout 场景中使用的 ID。例如:

<resources xmlns:tools="http://schemas.android.com/tools"
    tools:keep="@+id/beforeCrack,@+id/afterCrack,@+id/start"
    tools:shrinkMode="strict" />

将此文件放入您的 res 目录中。它确保所有指定的资源保留在最终版本中并且可供 MotionLayout 使用。

© www.soinside.com 2019 - 2024. All rights reserved.