android.content.res.Resources$NotFoundException: String resource ID #0x1

54560 단어 Android
안드로이드 개발에서android가 나오면content.res.Resources$NotFoundException:String resource ID #0x1과 같은 오류는 생각할 필요도 없습니다. Textview 컨트롤에 문제가 있는 것이 틀림없습니다. mTextview.setText.우리가 해야 할 일은eg:mTextview입니다.setText (1 + "), 즉 매개 변수가 문자열로 바뀌는 것입니다. 다음에 원본 코드를 보겠습니다.
컨트롤 TextView에 추가된 데이터가eg: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
 *
 * @see #setText(CharSequence)
 *
 * @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가string 형식이라면 볼 수 있습니다.이어서 getText () 를 살펴보겠습니다.
/**
 * Return the string value associated with a particular resource ID.  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
 *           tool. This integer encodes the package, type, and resource
 *           entry. The value 0 is an invalid identifier.
 *
 * @throws NotFoundException Throws NotFoundException if the given ID does not exist.
 *
 * @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.
 *
 * @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)) {
            return outValue.coerceToString();
        }
        return null;
    }
}

문자 시퀀스CharSequence를 반환합니다.그럼 어떻게
특정 자원과 연결된 문자열 검색
값.계속해서 소스 보기:
 
  
/**
 * Populates {@code outValue} with the data associated a particular
 * resource identifier for the current configuration.
 *
 * @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(
                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)) {
            return outValue.coerceToString();
        }
        return null;
    }
}

만약 대응하는 자원을 찾게 된다면 우리는 일련의 방법을 거쳐 문자 서열로 전환할 것이다.
코드는 다음과 같습니다.
/**
 * Regardless of the actual type of the value, 
try to convert it to a
 * string value.  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()
{
    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 The data type identifier.
 * @param data The data value.
 * 
 * @return String The coerced string value.  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 TYPE_NULL:
        return null;
    case TYPE_REFERENCE:
        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>>COMPLEX_UNIT_SHIFT)&COMPLEX_UNIT_MASK];
    case TYPE_FRACTION:
        return Float.toString(complexToFloat(data)*100) + FRACTION_UNIT_STRS[
            (data>>COMPLEX_UNIT_SHIFT)&COMPLEX_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에 추가된 데이터가eg: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
 * {@link android.text.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.Factory} to create final or
 * intermediate {@link Spannable Spannables}. Likewise it will use
 * {@link android.text.Editable.Factory} to create final or intermediate
 * {@link Editable Editables}.
 *
 * @param text text to be displayed
 *
 * @attr ref android.R.styleable#TextView_text
 */
@android.view.RemotableViewMethod
public final void setText(CharSequence text) {
    setText(text, mBufferType);
}

next2.
표시할 텍스트 설정
/**
 * Sets the text to be displayed and the {@link android.widget.TextView.BufferType}.
 * 
 * When required, TextView will use {@link android.text.Spannable.Factory} to create final or
 * intermediate {@link Spannable Spannables}. Likewise it will use
 * {@link android.text.Editable.Factory} to create final or intermediate
 * {@link Editable Editables}.
 *
 * @param text text to be displayed
 * @param type a {@link android.widget.TextView.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.BufferType
 * @see #setSpannableFactory(Spannable.Factory)
 * @see #setEditableFactory(Editable.Factory)
 *
 * @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();

좋은 웹페이지 즐겨찾기