【问题标题】:How to fix android.content.res.Resources$NotFoundException error?如何修复 android.content.res.Resources$NotFoundException 错误?
【发布时间】:2017-12-28 23:01:08
【问题描述】:

我已经在我的设备和几个模拟器上测试了该应用程序。该应用没有崩溃,我在 LogCat 上也看不到任何内容,但我可以在 22 小时内看到大约 400 次 ANR 和崩溃。

该错误没有说明缺少哪个资源来检查它以及如果它缺少为什么它没有在我的手机上崩溃?

这是导致崩溃的行:

int themeLayout = sharedPreferences.getInt(THEME_KEY, R.layout.input_1);
mInputView = (LatinKeyboardView) getLayoutInflater().inflate(
                themeLayout, null);

如果共享首选项返回 null,那么我分配了一个默认值来使用该值,但它仍然崩溃。我检查了布局,它存在,还要检查内容。

我创建了具有相同规格的模拟器,但它没有崩溃。

android.content.res.Resources$NotFoundException: 在 android.content.res.ResourcesImpl.getValue (ResourcesImpl.java:202)
在 android.content.res.Resources.loadXmlResourceParser (Resources.java:2968) 在 android.content.res.Resources.getLayout (Resources.java:1984) 在 android.view.LayoutInflater.inflate (LayoutInflater.java:425) 在 android.view.LayoutInflater.inflate (LayoutInflater.java:378) 在 com.sunzala.afghankeyboard.android.SoftKeyboard.onCreateInputView (SoftKeyboard.java:163) 在 com.sunzala.afghankeyboard.android.SoftKeyboard.onStartInput (SoftKeyboard.java:242) 在 android.inputmethodservice.InputMethodService.doStartInput (InputMethodService.java:2641) 在 android.inputmethodservice.InputMethodService$InputMethodImpl.startInput (InputMethodService.java:590) 在 android.inputmethodservice.IInputMethodWrapper.executeMessage (IInputMethodWrapper.java:186) 在 com.android.internal.os.HandlerCaller$MyHandler.handleMessage (HandlerCaller.java:37)

编辑: 我发现了这个错误:

E/dalvikvm: 找不到类 'android.graphics.drawable.RippleDrawable',引用自方法 android.support.v7.widget.AppCompatImageHelper.hasOverlappingRendering

【问题讨论】:

  • 我希望您的代码会因设置首选项的应用程序的某些更新而崩溃。资源 ID 可以在每次构建时更改。正如您所做的那样,它们可以安全地坚持下去。这是否是导致此特定崩溃的原因,我不能说,但您需要重新编写此代码以使用 you 控制的某些值作为首选项值,而不是资源 ID。
  • @CommonsWare 当应用程序第一次运行时,我用这一行 editor.putInt(THEME_KEY, R.layout.input_8).apply(); 存储价值。该值不是静态存储的。你觉得还重要吗?谢谢
  • 您引用为R.layout.input_8 的实际int 值可能因构建而异。您今天保存在SharedPreferences 中的值可能会在用户升级到您的应用程序的较新版本后的一周内失效。不要保留 R 值,因为它们在构建之间不是恒定的。

标签: android android-layout


【解决方案1】:

我们在 Java 代码中引用的 R 值(例如 R.layout.input_8)是代码生成的 R 类上的 public static final int 值。您将在模块的build/generated/source/r/ 目录中找到该类。该文件将相当大,但您会看到如下内容:

  public static final class layout {
    public static final int activity_main=0x7f050000;
  }

该数字 (0x7f050000) 由构建工具 (aapt,特别是 IIRC) 生成。 该值可能会因构建而异。因此,坚持这样的数字是不安全的。否则,你会遇到这样的场景:

  • 用户安装您的应用

  • 用户在您的应用中执行了一些导致您保留值的操作(例如,editor.putInt(THEME_KEY, R.layout.input_8).apply();

  • 时间流逝

  • 您将更新发送到您的应用,结果发现R.layout.input_8 的编号发生了变化

  • 用户将更新安装到您的应用中

  • 您的代码调用sharedPreferences.getInt(THEME_KEY, R.layout.input_1); 并检索一个曾经作为资源ID的数字...但现在只是一个数字,或者指向一些不同的资源

  • 您的代码崩溃

  • 用户感到沮丧,将手机扔到墙上

注意:在创建此场景时,没有实际的电话或墙壁受到伤害

这是您的代码一个问题。我不知道是不是 问题触发了您的崩溃,但它可能是。

问题在于您保留了一个您无法控制的值 (0x7f050000)。你认为R.layout.input_8 永远是0x7f050000,但事实并非如此。

您需要做的是在首选项中存储其他内容,然后使用它来查找正确的 ID。有两种主要方法。

一种是使用简单的索引。您的命名方案表明您有一系列编号的布局,至少通过8。因此,您可以在SharedPreferences 中保存一个介于18 之间的数字,然后将其用作数组的索引:

static final int[] THE_LAYOUTS={R.layout.input_1, R.layout.input_2, R.layout.input_3, R.layout.input_4, R.layout.input_5, R.layout.input_6, R.layout.input_7, R.layout.input_8};

在此解决方案中,editor.putInt(THEME_KEY, R.layout.input_8).apply(); 变为 editor.putInt(THEME_KEY, 8).apply();sharedPreferences.getInt(THEME_KEY, R.layout.input_1); 变为 THE_LAYOUTS[sharedPreferences.getInt(THEME_KEY, 1)];

另一种是保存字符串 "R.layout.input_8"。鉴于此,以及Resources 对象上的getIdentifier(),您可以取回与当前构建的该字符串关联的int 值。就我个人而言,我觉得这更尴尬也更慢,但这是一种选择。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-05-26
    • 1970-01-01
    • 2019-05-31
    • 2020-02-28
    • 2017-06-29
    • 2014-11-18
    相关资源
    最近更新 更多