Resources$NotFoundException 无法为 Drawable 找到资源 ID #0x7f080043

Resources$NotFoundException Unable to find resource ID #0x7f080043 for Drawable

我的应用程序用户在 Crashlytics 中遇到错误:由于 android.content.res.Resources$NotFoundException 无法找到可绘制对象的资源 ID #0x7f080043。我在我的 APK(正在调试)中检查了它,发现它与可绘制的“abc_spinner_mtrl_am_alpha”有关。我在微调器的后台使用这个可绘制对象。我不是自己创建这个可绘制对象,它来自库 appcompat-1.4.1。但是在这个库中,它以多种密度存在等等。有没有人遇到过类似的问题并且知道它的解决方案/根本原因?

Caused by android.content.res.Resources$NotFoundException: Unable to find resource ID #0x7f080043
       at android.content.res.ResourcesImpl.getResourceName(ResourcesImpl.java:253)
       at android.content.res.ResourcesImpl.loadDrawableForCookie(ResourcesImpl.java:760)
       at android.content.res.ResourcesImpl.loadDrawable(ResourcesImpl.java:630)
       at android.content.res.Resources.loadDrawable(Resources.java:886)
       at android.content.res.TypedArray.getDrawableForDensity(TypedArray.java:953)
       at android.content.res.TypedArray.getDrawable(TypedArray.java:928)
       at android.content.res.XResources$XTypedArray.getDrawable(XResources.java:1363)
       at android.view.View.<init>(View.java:4768)
       at android.widget.TextView.<init>(TextView.java:826)
       at android.widget.TextView.<init>(TextView.java:820)
       at androidx.appcompat.widget.AppCompatTextView.<init>(AppCompatTextView.java:108)
       at androidx.appcompat.widget.AppCompatTextView.<init>(AppCompatTextView.java:103)
       at androidx.appcompat.app.AppCompatViewInflater.createTextView(AppCompatViewInflater.java:201)
       at androidx.appcompat.app.AppCompatViewInflater.createView(AppCompatViewInflater.java:121)
       at androidx.appcompat.app.AppCompatDelegateImpl.createView(AppCompatDelegateImpl.java:1566)
       at androidx.appcompat.app.AppCompatDelegateImpl.onCreateView(AppCompatDelegateImpl.java:1617)
       at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:772)
       at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:730)
       at android.view.LayoutInflater.inflate(LayoutInflater.java:492)
       at android.view.LayoutInflater.inflate(LayoutInflater.java:423)
       at android.widget.ArrayAdapter.createViewFromResource(ArrayAdapter.java:416)
       at android.widget.ArrayAdapter.getView(ArrayAdapter.java:407)
       at android.widget.AbsSpinner.onMeasure(AbsSpinner.java:204)
       at android.widget.Spinner.onMeasure(Spinner.java:602)
       at androidx.appcompat.widget.AppCompatSpinner.onMeasure(AppCompatSpinner.java:438)
       at android.view.View.measure(View.java:22071)
       at androidx.constraintlayout.widget.ConstraintLayout$Measurer.measure(ConstraintLayout.java:811)
       at androidx.constraintlayout.core.widgets.analyzer.BasicMeasure.measure(BasicMeasure.java:466)
       at androidx.constraintlayout.core.widgets.analyzer.BasicMeasure.solverMeasure(BasicMeasure.java:372)
       at androidx.constraintlayout.core.widgets.ConstraintWidgetContainer.measure(ConstraintWidgetContainer.java:120)
       at androidx.constraintlayout.widget.ConstraintLayout.resolveSystem(ConstraintLayout.java:1594)
       at androidx.constraintlayout.widget.ConstraintLayout.onMeasure(ConstraintLayout.java:1708)
       at android.view.View.measure(View.java:22071)
       at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6602)
       at android.widget.FrameLayout.onMeasure(FrameLayout.java:185)
       at androidx.appcompat.widget.ContentFrameLayout.onMeasure(ContentFrameLayout.java:145)
       at android.view.View.measure(View.java:22071)
       at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6602)
       at androidx.appcompat.widget.ActionBarOverlayLayout.onMeasure(ActionBarOverlayLayout.java:496)
       at android.view.View.measure(View.java:22071)
       at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6602)
       at android.widget.FrameLayout.onMeasure(FrameLayout.java:185)
       at android.view.View.measure(View.java:22071)
       at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6602)
       at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1514)
       at android.widget.LinearLayout.measureVertical(LinearLayout.java:806)
       at android.widget.LinearLayout.onMeasure(LinearLayout.java:685)
       at android.view.View.measure(View.java:22071)
       at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6602)
       at android.widget.FrameLayout.onMeasure(FrameLayout.java:185)
       at com.android.internal.policy.DecorView.onMeasure(DecorView.java:724)
       at android.view.View.measure(View.java:22071)
       at android.view.ViewRootImpl.performMeasure(ViewRootImpl.java:2422)
       at android.view.ViewRootImpl.measureHierarchy(ViewRootImpl.java:1504)
       at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1761)
       at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1392)
       at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:6752)
       at android.view.Choreographer$CallbackRecord.run(Choreographer.java:911)
       at android.view.Choreographer.doCallbacks(Choreographer.java:723)
       at android.view.Choreographer.doFrame(Choreographer.java:658)
       at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:897)
       at android.os.Handler.handleCallback(Handler.java:790)
       at android.os.Handler.dispatchMessage(Handler.java:99)
       at android.os.Looper.loop(Looper.java:164)
       at android.app.ActivityThread.main(ActivityThread.java:6494)
       at java.lang.reflect.Method.invoke(Method.java)
       at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:438)
       at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:807) 

可能是因为资源在默认文件夹中没有文件(仅在 xxhdpi 和 ldrtl-xxhdpi 文件夹中)。应用程序崩溃的 phone 可能具有不同的密度,并且该应用程序 deployed/installed 作为 android 应用程序包 (.aab) 启用 google 播放以删除它认为不必要的资源(比如这个资源,考虑到它的不同密度,该设备不需要)来减少包大小。

一种解决方法是将该资源复制到您的项目中(最好使用不同的名称以防止出现其他问题)并将其直接放置在 resources/drawables 文件夹下或所有可绘制对象文件夹中,具体取决于其尺寸(如果任何)。这应该确保它存在于所有应用程序包中,无论它们的目标屏幕密度如何。


回复评论:

是的,尽管 android gradle 插件可能在构建日志中记录了一个 error/warning 关于未为所有密度提供有问题的可绘制对象,但确实是一个错误。 rule/recommendation 要么在 drawables 文件夹中有一个 drawable,要么在每个 mdpi、hdpi、xhdpi、xxhdpi 文件夹中都有副本(按比例大小)。对于这个支持库,它只提供了一个 xxhdpi 版本,并且可能在运行时库只在 xxhdpi 设备上使用 drawable。这是一个 9 补丁图像,因此可以安全地将其复制到可绘制对象中而不会降低质量。

理想情况下,大多数图形都包含矢量可绘制对象,can/should 将其放置在可绘制对象中而不用担心设备密度。请注意矢量可绘制对象的宽度和高度属性,因为这些属性将决定它在屏幕上显示的大小,如果缺少这些属性,则将从视图的大小推断出大小(wrap_content 可能导致可绘制对象无法显示可见)。 在使用 aab 格式部署应用程序时,请始终注意为所有设备配置(密度、屏幕方向等)提供资源,因为设备下载的最终存档可能只有其密度 and/or 的资源默认值(可绘制对象、值)。在过去(使用 apk 格式),android 运行时会在密度较高的可绘制对象和默认可绘制对象不可用时尝试缩小更高密度的可绘制对象。现在(使用 aab)更高密度的可绘制对象被排除在捆绑包之外,这不再可能了。

我还认为最好不要直接使用第三方库中的资源(比如从您的布局中引用它们),因为它们很容易被重命名、移动或删除(尤其是动态 gradle 依赖项)使用 complex/non-deterministic android 构建系统,在发布的应用程序在用户设备上崩溃之前,它可能不会变得明显。如果您确实需要库中的某些资源,最好将其复制到您的项目中。一般来说,尽可能少地依赖你无法控制的事情会更安全。