1. ホーム
  2. Android

android.content.res.Resources$NotFoundException: 文字列リソースID #0x1

2022-02-18 15:59:46

android.content.res.Resources$NotFoundException のようなエラーが発生した場合。Androidの開発で文字列リソースID #0x1が出たら、考えなくてもきっと テキストビュー データを表示するコントロール:mTextview.setText(ここで、入力されるデータはint型として記述されなければならない)に問題があります。私たちが行う必要があることは、例えば、次のとおりです。 mTextview.setText (1+"")、つまりは パラメータ が文字列に変換されていることを確認し、ソースコードを見ると


コントロールTextViewに追加されるデータが、例えば、mTextview.setText(1)のように書かれている場合、つまり、数字が渡される場合、ソースコードは次のように解析されます。


<テーブル
/*
 * Sets the text to be displayed using a string resource identifier.
 *
 * @param resid the resource identifier of the string resource to be displayed
 * @param resid the resource identifier of the string resource to be displayed.
 * @see #setText(CharSequence)
 * @attr ref android.
 * @attr ref android.R.styleable#TextView_text
 */
@android.view.RemotableViewMethod
public final void setText(@StringRes int resid) {
    setText(getContext().getResources().getText(resid));
    mTextFromResource = true;
}







このメソッドのコメントから、パラメータresidが文字列型であることがわかります。次に、getText() に下りてみます。


<テーブル
/**
 * Return the string value associated with a particular resource ID.
 * returned object will be a String if this is a plain string; it will be
 The * returned object will be a String if this is a plain string; it will be * some other type of CharSequence if it is styled.
 * {@more}
 * @param id
 * The desired resource identifier, as generated by the aapt
 This integer encodes the package, type, and resource * entry.
 * The value 0 is an invalid identifier.
 *The value 0 is an invalid identifier.
 * @throws NotFoundException Throws NotFoundException if the given ID does not exist.
 * @throws NotFoundException
 * @return CharSequence The string data associated with the resource, plus
 * possibly styled text information.
 */
@NonNull public CharSequence getText(@StringRes int id) throws NotFoundException {
    CharSequence res = mResourcesImpl.getAssets().getResourceText(id);
    if (res ! = null) {
        return res;
    }
    throw new NotFoundException("String resource ID #0x"
            + Integer.toHexString(id));
}








上記の意味はおそらく 指定されたリソース ID に関連する文字列値を返します。 返されるオブジェクトは、これが通常の文字列であれば、文字列となります。 @param id : 必要なリソース識別子です。 aaptツールで生成されます。 この整数は、パッケージ、タイプ、リソースをエンコードします。 のエントリで、値 0 は無効な識別子である。クラスAssetManagerに移ります。

<スパン <スパン

<スパン <スパン


<スパン


<テーブル





/**
 * Retrieves the string value associated with a particular resource
 * identifier for the current configuration.
 * Retrieves the string value associated with a particular resource identifier for the current configuration.
 * @param resId the resource identifier to load
 * @return the string value, or {@code null}
 */
@Nullable
final CharSequence getResourceText(@StringRes int resId) {
    synchronized (this) {
        final TypedValue outValue = mValue;
        if (getResourceValue(resId, 0, outValue, true)) { if (getResourceValue(resId, 0, outValue, true))
            return outValue.coerceToString();
        }
        return null;
    }
}






文字列CharSequenceを返します。 では、どのように 特定のリソースに関連する文字列を取得する の値を指定します。
ソースコードの続きです。


<テーブル




/**
 * Populates {@code outValue} with the data associated a particular
 * resource identifier for the current configuration.
 * @param resId
 * @param resId the resource identifier to load
 * @param densityDpi the density bucket for which to load the resource
 * @param outValue the typed value in which to put the data
 * @param resolveRefs {@code true} to resolve references, {@code false}
 * to leave them unresolved
 * @return {@code true} if the data was loaded into {@code outValue},
 * {@code false} otherwise
 */
final boolean getResourceValue(@AnyRes int resId, int densityDpi, @NonNull TypedValue outValue,
        boolean resolveRefs) {
    synchronized (this) {
        final int block = loadResourceValue(resId, (short) densityDpi, outValue, resolveRefs);
        if (block < 0) {
            return false;
        }

        // Convert the changing configurations flags populated by native code.
        outValue.changingConfigurations = ActivityInfo.activityInfoConfigNativeToJava(
                activityInfoConfigNativeToJava( outValue.changingConfigurations);

        if (outValue.type == TypedValue.TYPE_STRING) {
            outValue.string = mStringBlocks[block].get(outValue.data);
        }
        return true;
    }
}







/** Returns true if the resource was found, filling in mRetStringBlock and
 * mRetData. */
private native final int loadResourceValue(int ident, short density, TypedValue outValue,
        boolean resolve);






対応するリソースが見つかった場合に true を返します。ここでは、ネイティブメソッド
それは、c/c++が何かをしようとしているに違いない、我々はそれを考えていない。もし見つからなければ、nullを返します。
このことは、次のコードからわかる。
<テーブル
@Nullable
final CharSequence getResourceText(@StringRes int resId) {
    synchronized (this) {
        final TypedValue outValue = mValue;
        if (getResourceValue(resId, 0, outValue, true)) { if (getResourceValue(resId, 0, outValue, true))
            return outValue.coerceToString();
        }
        return null;
    }
}









対応するリソースが見つかったら、それを文字列に変換するための一連のメソッドを実行します。
コードは以下の通りです。
<テーブル
/**
 * Regardless of the actual type of the value, 
try to convert it to a
 * For example, a color type will be converted 
For example, a color type will be converted to a
 For example, a color type will be converted to a * string of the form #aarrggbb.
 For example, a color type will be converted to a * string of the form #aarrggbb. 
 * @return CharSequence The coerced string value.  
If the value is
 * null or the type is not known, null is returned.
 */
public final CharSequence coerceToString()
coerceToString() {
    int t = type;
    if (t == TYPE_STRING) {
        return string;
    }
    return coerceToString(t, data);
}


 2. ------------------------------------------
/**
 * Perform type conversion as per {@link #coerceToString()} on an
 * explicitly supplied type and data.
 * @param type 
 * @param type The data type identifier.
 * @param data The data value.
 * @param data The data value. 
 * If the value is null or the type is not known, null is returned.
 If the value is * null or the type is not known, null is returned.
 */
public static final String coerceToString(int type, int data)
{
    switch (type) { case
    case TYPE_NULL:
        return null;
    case TYPE_REFERENCE:
        return "@" + data;
    case TYPE_ATTRIBUTE:
        return "@" + data; case TYPE_ATTRIBUTE: return "@" " + data;
    case TYPE_FLOAT:
        return Float.toString(Float.intBitsToFloat(data));
    case TYPE_DIMENSION:
        return Float.toString(complexToFloat(data)) + DIMENSION_UNIT_STRS[
            (data>>COMPLLEX_UNIT_SHIFT)&COMPLLEX_UNIT_MASK];
    case TYPE_FRACTION:
        return Float.toString(complexToFloat(data)*100) + FRACTION_UNIT_STRS[
            (data>>COMPLLEX_UNIT_SHIFT)&COMPLLEX_UNIT_MASK];
    case TYPE_INT_HEX:
        return "0x" + Integer.toHexString(data);
    case TYPE_INT_BOOLEAN:
        return data ! = 0 ? "true" : "false";
    }

    if (type >= TYPE_FIRST_COLOR_INT && type <= TYPE_LAST_COLOR_INT) {
        return "#" + Integer.toHexString(data);
    } else if (type >= TYPE_FIRST_INT && type <= TYPE_LAST_INT) {
        return Integer.toString(data);
    }

    return null;
}


...........................

コントロールTextViewで追加されるデータが、例えば、mTextview.setText(1+"")のように書かれている場合、つまり、文字列が渡された場合、ソースコードは、以下のように解析されます。


next1.
<テーブル
/*
 * Sets the text to be displayed. textView 


does not accept
 * HTML-like formatting, which you can do with text strings in XML resource files.
 * To style your strings, attach android.text.style.* objects to a
 * SpannableString}, or see the
 SpannableString}, or see the * {@docRoot}guide/topics/resources/available-resources.html#stringresources">
 * Available Resource Types documentation for an example of setting
 * formatted text in the XML resource file.
 * 



 * When required, TextView will use {@link android.text.
 Spannable Spannables} to create final or * intermediate {@link Spannable Spannables}. Likewise it will use
 Likewise it will use * {@link android.text.
 * Editable.
 Likewise it will use * {@link android.text.
 * @param text text to be displayed
 *@param text to be displayed.
 * @attr ref android.R.styleable#TextView_text
 */
@android.view.RemotableViewMethod
public final void setText(CharSequence text) {
    setText(text, mBufferType);
}








/**
 * Sets the text to be displayed and the {@link android.widget.TextView.}
 * 



 * When required, TextView will use {@link android.text.
 Spannable Spannables} to create final or * intermediate {@link Spannable Spannables}. Likewise it will use
 Likewise it will use * {@link android.text.
 * Editable.
 Likewise it will use * {@link android.text.
 * @param text text to be displayed
 * BufferType} which defines whether the text is
 BufferType} which defines whether the text is * stored as a static text, styleable/spannable text, or editable text
 *
 * @see #setText(CharSequence)
 * @see android.widget.TextView.
 * @see #setSpannableFactory(Spannable.)
 * @see #setEditableFactory(Editable.)
 * @see
 * @attr ref android.R.styleable#TextView_text
 * @attr ref android.R.styleable#TextView_bufferType
 */
public void setText(CharSequence text, BufferType type) {
    setText(text, type, true, 0);

    if (mCharWrapper ! = null) {
        mCharWrapper.mChars = null;
    }
}

private void setText(CharSequence text, BufferType type, boolean notifyBefore, int oldlen) { mTextFromResource = false; if (text == null) { text = ""; } // If suggestions are not enabled, remove the suggestion spans from the text if (!isSuggestionsEnabled()) { text = removeSuggestionSpans(text); }


next2.

表示するテキストを設定する

<テーブル
notifyViewAccessibilityStateChangedIfNeeded(AccessibilityEvent.CONTENT_CHANGE_TYPE_TEXT);

if (needEditableForNotification) {
    sendAfterTextChanged((Editable) text);
} else {
    // Always notify AutoFillManager - it will return right away if autofill is disabled.
    notifyAutoFillManagerAfterTextChangedIfNeeded();
}

// SelectionModifierCursorController depends on textCanBeSelected, which depends on text
if (mEditor ! = null) mEditor.prepareCursorControllers();

* When required, TextView will use {@link android.text. Spannable Spannables} to create final or * intermediate {@link Spannable Spannables}. Likewise it will use Likewise it will use * {@link android.text. * Editable. Likewise it will use * {@link android.text. * @param text text to be displayed * BufferType} which defines whether the text is BufferType} which defines whether the text is * stored as a static text, styleable/spannable text, or editable text * * @see #setText(CharSequence) * @see android.widget.TextView. * @see #setSpannableFactory(Spannable.) * @see #setEditableFactory(Editable.) * @see * @attr ref android.R.styleable#TextView_text * @attr ref android.R.styleable#TextView_bufferType */ public void setText(CharSequence text, BufferType type) { setText(text, type, true, 0); if (mCharWrapper ! = null) { mCharWrapper.mChars = null; } }

next3.

<テーブル
private void setText(CharSequence text, BufferType type,
                     boolean notifyBefore, int oldlen) {
    mTextFromResource = false;
    if (text == null) {
        text = "";
    }

    // If suggestions are not enabled, remove the suggestion spans from the text
    if (!isSuggestionsEnabled()) {
        text = removeSuggestionSpans(text);
    }


    ............

    .................

    .........


notifyViewAccessibilityStateChangedIfNeeded(AccessibilityEvent.CONTENT_CHANGE_TYPE_TEXT);

if (needEditableForNotification) {
    sendAfterTextChanged((Editable) text);
} else {
    // Always notify AutoFillManager - it will return right away if autofill is disabled.
    notifyAutoFillManagerAfterTextChangedIfNeeded();
}

// SelectionModifierCursorController depends on textCanBeSelected, which depends on text
if (mEditor ! = null) mEditor.prepareCursorControllers();