diff options
author | Alan Viverette <alanv@google.com> | 2015-01-05 18:12:44 -0800 |
---|---|---|
committer | Alan Viverette <alanv@google.com> | 2015-01-06 11:05:33 -0800 |
commit | 6bbb47b7d5ac1b49d916679e5f081fe181d8f162 (patch) | |
tree | a0b4f4b3548719af44ee36126d9944294c672f1e /core/java/android/content | |
parent | 304ea5aac77cae03b4e8440a7c73c18086d96a20 (diff) | |
download | frameworks_base-6bbb47b7d5ac1b49d916679e5f081fe181d8f162.zip frameworks_base-6bbb47b7d5ac1b49d916679e5f081fe181d8f162.tar.gz frameworks_base-6bbb47b7d5ac1b49d916679e5f081fe181d8f162.tar.bz2 |
Clean up TypedArray docs & formatting, remove coercion warnings
Establishes a clear contract regarding when exceptions will be thrown,
when default values will be returned, and when values will be coerced
to a different type.
Since we have both getInt() and getInteger() where one handles coercion
without throwing an exception, it seems reasonable that we should clearly
document the behavior so that developers can make an informed decision.
Once we document the behavior, there is no reason to log warnings on
coercion. If a developer chooses to use a particular API or data type,
that is still correct according to the API.
BUG: 18625719
Change-Id: I385f0b719182d3c0358943e1d6c3d7bedc756eb5
Diffstat (limited to 'core/java/android/content')
-rw-r--r-- | core/java/android/content/res/Resources.java | 4 | ||||
-rw-r--r-- | core/java/android/content/res/TypedArray.java | 330 |
2 files changed, 231 insertions, 103 deletions
diff --git a/core/java/android/content/res/Resources.java b/core/java/android/content/res/Resources.java index c5c8d75..c931c01 100644 --- a/core/java/android/content/res/Resources.java +++ b/core/java/android/content/res/Resources.java @@ -2696,8 +2696,8 @@ public class Resources { private ColorStateList loadColorStateListForCookie(TypedValue value, int id, Theme theme) { if (value.string == null) { - throw new NotFoundException("Resource \"" + getResourceName(id) + "\" (" - + Integer.toHexString(id) + ") is not a ColorStateList: " + value); + throw new UnsupportedOperationException( + "Can't convert to color state list: type=0x" + value.type); } final String file = value.string.toString(); diff --git a/core/java/android/content/res/TypedArray.java b/core/java/android/content/res/TypedArray.java index 06c701a..f15b6b9 100644 --- a/core/java/android/content/res/TypedArray.java +++ b/core/java/android/content/res/TypedArray.java @@ -18,6 +18,7 @@ package android.content.res; import android.annotation.Nullable; import android.graphics.drawable.Drawable; +import android.os.StrictMode; import android.util.AttributeSet; import android.util.DisplayMetrics; import android.util.Log; @@ -73,7 +74,9 @@ public class TypedArray { /*package*/ TypedValue mValue = new TypedValue(); /** - * Return the number of values in this array. + * Returns the number of values in this array. + * + * @throws RuntimeException if the TypedArray has already been recycled. */ public int length() { if (mRecycled) { @@ -85,6 +88,8 @@ public class TypedArray { /** * Return the number of indices in the array that actually have data. + * + * @throws RuntimeException if the TypedArray has already been recycled. */ public int getIndexCount() { if (mRecycled) { @@ -95,13 +100,14 @@ public class TypedArray { } /** - * Return an index in the array that has data. + * Returns an index in the array that has data. * * @param at The index you would like to returned, ranging from 0 to - * {@link #getIndexCount()}. + * {@link #getIndexCount()}. * * @return The index at the given offset, which can be used with - * {@link #getValue} and related APIs. + * {@link #getValue} and related APIs. + * @throws RuntimeException if the TypedArray has already been recycled. */ public int getIndex(int at) { if (mRecycled) { @@ -112,7 +118,9 @@ public class TypedArray { } /** - * Return the Resources object this array was loaded from. + * Returns the Resources object this array was loaded from. + * + * @throws RuntimeException if the TypedArray has already been recycled. */ public Resources getResources() { if (mRecycled) { @@ -123,12 +131,17 @@ public class TypedArray { } /** - * Retrieve the styled string value for the attribute at <var>index</var>. + * Retrieves the styled string value for the attribute at <var>index</var>. + * <p> + * If the attribute is not a string, this method will attempt to coerce + * it to a string. * * @param index Index of attribute to retrieve. * - * @return CharSequence holding string data. May be styled. Returns - * null if the attribute is not defined. + * @return CharSequence holding string data. May be styled. Returns + * {@code null} if the attribute is not defined or could not be + * coerced to a string. + * @throws RuntimeException if the TypedArray has already been recycled. */ public CharSequence getText(int index) { if (mRecycled) { @@ -144,23 +157,28 @@ public class TypedArray { return loadStringValueAt(index); } - TypedValue v = mValue; + final TypedValue v = mValue; if (getValueAt(index, v)) { - Log.w(Resources.TAG, "Converting to string: " + v); + StrictMode.noteResourceMismatch(v); return v.coerceToString(); } - Log.w(Resources.TAG, "getString of bad type: 0x" - + Integer.toHexString(type)); - return null; + + // We already checked for TYPE_NULL. This should never happen. + throw new RuntimeException("getText of bad type: 0x" + Integer.toHexString(type)); } /** - * Retrieve the string value for the attribute at <var>index</var>. + * Retrieves the string value for the attribute at <var>index</var>. + * <p> + * If the attribute is not a string, this method will attempt to coerce + * it to a string. * * @param index Index of attribute to retrieve. * - * @return String holding string data. Any styling information is - * removed. Returns null if the attribute is not defined. + * @return String holding string data. Any styling information is removed. + * Returns {@code null} if the attribute is not defined or could + * not be coerced to a string. + * @throws RuntimeException if the TypedArray has already been recycled. */ public String getString(int index) { if (mRecycled) { @@ -176,19 +194,19 @@ public class TypedArray { return loadStringValueAt(index).toString(); } - TypedValue v = mValue; + final TypedValue v = mValue; if (getValueAt(index, v)) { - Log.w(Resources.TAG, "Converting to string: " + v); - CharSequence cs = v.coerceToString(); + StrictMode.noteResourceMismatch(v); + final CharSequence cs = v.coerceToString(); return cs != null ? cs.toString() : null; } - Log.w(Resources.TAG, "getString of bad type: 0x" - + Integer.toHexString(type)); - return null; + + // We already checked for TYPE_NULL. This should never happen. + throw new RuntimeException("getString of bad type: 0x" + Integer.toHexString(type)); } /** - * Retrieve the string value for the attribute at <var>index</var>, but + * Retrieves the string value for the attribute at <var>index</var>, but * only if that string comes from an immediate value in an XML file. That * is, this does not allow references to string resources, string * attributes, or conversions from other types. As such, this method @@ -197,9 +215,10 @@ public class TypedArray { * * @param index Index of attribute to retrieve. * - * @return String holding string data. Any styling information is - * removed. Returns null if the attribute is not defined or is not - * an immediate string value. + * @return String holding string data. Any styling information is removed. + * Returns {@code null} if the attribute is not defined or is not + * an immediate string value. + * @throws RuntimeException if the TypedArray has already been recycled. */ public String getNonResourceString(int index) { if (mRecycled) { @@ -220,16 +239,17 @@ public class TypedArray { } /** - * @hide - * Retrieve the string value for the attribute at <var>index</var> that is + * Retrieves the string value for the attribute at <var>index</var> that is * not allowed to change with the given configurations. * * @param index Index of attribute to retrieve. * @param allowedChangingConfigs Bit mask of configurations from - * {@link Configuration}.NATIVE_CONFIG_* that are allowed to change. + * {@link Configuration}.NATIVE_CONFIG_* that are allowed to change. * - * @return String holding string data. Any styling information is - * removed. Returns null if the attribute is not defined. + * @return String holding string data. Any styling information is removed. + * Returns {@code null} if the attribute is not defined. + * @throws RuntimeException if the TypedArray has already been recycled. + * @hide */ public String getNonConfigurationString(int index, int allowedChangingConfigs) { if (mRecycled) { @@ -248,24 +268,33 @@ public class TypedArray { return loadStringValueAt(index).toString(); } - TypedValue v = mValue; + final TypedValue v = mValue; if (getValueAt(index, v)) { - Log.w(Resources.TAG, "Converting to string: " + v); - CharSequence cs = v.coerceToString(); + StrictMode.noteResourceMismatch(v); + final CharSequence cs = v.coerceToString(); return cs != null ? cs.toString() : null; } - Log.w(Resources.TAG, "getString of bad type: 0x" - + Integer.toHexString(type)); - return null; + + // We already checked for TYPE_NULL. This should never happen. + throw new RuntimeException("getNonConfigurationString of bad type: 0x" + + Integer.toHexString(type)); } /** * Retrieve the boolean value for the attribute at <var>index</var>. + * <p> + * If the attribute is an integer value, this method will return whether + * it is equal to zero. If the attribute is not a boolean or integer value, + * this method will attempt to coerce it to an integer using + * {@link Integer#decode(String)} and return whether it is equal to zero. * * @param index Index of attribute to retrieve. - * @param defValue Value to return if the attribute is not defined. + * @param defValue Value to return if the attribute is not defined or + * cannot be coerced to an integer. * - * @return Attribute boolean value, or defValue if not defined. + * @return Boolean value of the attribute, or defValue if the attribute was + * not defined or could not be coerced to an integer. + * @throws RuntimeException if the TypedArray has already been recycled. */ public boolean getBoolean(int index, boolean defValue) { if (mRecycled) { @@ -278,28 +307,33 @@ public class TypedArray { if (type == TypedValue.TYPE_NULL) { return defValue; } else if (type >= TypedValue.TYPE_FIRST_INT - && type <= TypedValue.TYPE_LAST_INT) { + && type <= TypedValue.TYPE_LAST_INT) { return data[index+AssetManager.STYLE_DATA] != 0; } - TypedValue v = mValue; + final TypedValue v = mValue; if (getValueAt(index, v)) { - Log.w(Resources.TAG, "Converting to boolean: " + v); - return XmlUtils.convertValueToBoolean( - v.coerceToString(), defValue); + StrictMode.noteResourceMismatch(v); + return XmlUtils.convertValueToBoolean(v.coerceToString(), defValue); } - Log.w(Resources.TAG, "getBoolean of bad type: 0x" - + Integer.toHexString(type)); - return defValue; + + // We already checked for TYPE_NULL. This should never happen. + throw new RuntimeException("getBoolean of bad type: 0x" + Integer.toHexString(type)); } /** * Retrieve the integer value for the attribute at <var>index</var>. + * <p> + * If the attribute is not an integer, this method will attempt to coerce + * it to an integer using {@link Integer#decode(String)}. * * @param index Index of attribute to retrieve. - * @param defValue Value to return if the attribute is not defined. + * @param defValue Value to return if the attribute is not defined or + * cannot be coerced to an integer. * - * @return Attribute int value, or defValue if not defined. + * @return Integer value of the attribute, or defValue if the attribute was + * not defined or could not be coerced to an integer. + * @throws RuntimeException if the TypedArray has already been recycled. */ public int getInt(int index, int defValue) { if (mRecycled) { @@ -312,27 +346,31 @@ public class TypedArray { if (type == TypedValue.TYPE_NULL) { return defValue; } else if (type >= TypedValue.TYPE_FIRST_INT - && type <= TypedValue.TYPE_LAST_INT) { + && type <= TypedValue.TYPE_LAST_INT) { return data[index+AssetManager.STYLE_DATA]; } - TypedValue v = mValue; + final TypedValue v = mValue; if (getValueAt(index, v)) { - Log.w(Resources.TAG, "Converting to int: " + v); - return XmlUtils.convertValueToInt( - v.coerceToString(), defValue); + StrictMode.noteResourceMismatch(v); + return XmlUtils.convertValueToInt(v.coerceToString(), defValue); } - Log.w(Resources.TAG, "getInt of bad type: 0x" - + Integer.toHexString(type)); - return defValue; + + // We already checked for TYPE_NULL. This should never happen. + throw new RuntimeException("getInt of bad type: 0x" + Integer.toHexString(type)); } /** * Retrieve the float value for the attribute at <var>index</var>. + * <p> + * If the attribute is not a float or an integer, this method will attempt + * to coerce it to a float using {@link Float#parseFloat(String)}. * * @param index Index of attribute to retrieve. * - * @return Attribute float value, or defValue if not defined.. + * @return Attribute float value, or defValue if the attribute was + * not defined or could not be coerced to a float. + * @throws RuntimeException if the TypedArray has already been recycled. */ public float getFloat(int index, float defValue) { if (mRecycled) { @@ -347,21 +385,21 @@ public class TypedArray { } else if (type == TypedValue.TYPE_FLOAT) { return Float.intBitsToFloat(data[index+AssetManager.STYLE_DATA]); } else if (type >= TypedValue.TYPE_FIRST_INT - && type <= TypedValue.TYPE_LAST_INT) { + && type <= TypedValue.TYPE_LAST_INT) { return data[index+AssetManager.STYLE_DATA]; } - TypedValue v = mValue; + final TypedValue v = mValue; if (getValueAt(index, v)) { - Log.w(Resources.TAG, "Converting to float: " + v); - CharSequence str = v.coerceToString(); + final CharSequence str = v.coerceToString(); if (str != null) { + StrictMode.noteResourceMismatch(v); return Float.parseFloat(str.toString()); } } - Log.w(Resources.TAG, "getFloat of bad type: 0x" - + Integer.toHexString(type)); - return defValue; + + // We already checked for TYPE_NULL. This should never happen. + throw new RuntimeException("getFloat of bad type: 0x" + Integer.toHexString(type)); } /** @@ -369,12 +407,18 @@ public class TypedArray { * the attribute references a color resource holding a complex * {@link android.content.res.ColorStateList}, then the default color from * the set is returned. + * <p> + * This method will throw an exception if the attribute is defined but is + * not an integer color or color state list. * * @param index Index of attribute to retrieve. * @param defValue Value to return if the attribute is not defined or * not a resource. * * @return Attribute color value, or defValue if not defined. + * @throws RuntimeException if the TypedArray has already been recycled. + * @throws UnsupportedOperationException if the attribute is defined but is + * not an integer color or color state list. */ public int getColor(int index, int defValue) { if (mRecycled) { @@ -387,7 +431,7 @@ public class TypedArray { if (type == TypedValue.TYPE_NULL) { return defValue; } else if (type >= TypedValue.TYPE_FIRST_INT - && type <= TypedValue.TYPE_LAST_INT) { + && type <= TypedValue.TYPE_LAST_INT) { return data[index+AssetManager.STYLE_DATA]; } else if (type == TypedValue.TYPE_STRING) { final TypedValue value = mValue; @@ -398,7 +442,8 @@ public class TypedArray { } return defValue; } else if (type == TypedValue.TYPE_ATTRIBUTE) { - throw new RuntimeException("Failed to resolve attribute at index " + index); + throw new UnsupportedOperationException( + "Failed to resolve attribute at index " + index); } throw new UnsupportedOperationException("Can't convert to color: type=0x" @@ -408,12 +453,22 @@ public class TypedArray { /** * Retrieve the ColorStateList for the attribute at <var>index</var>. * The value may be either a single solid color or a reference to - * a color or complex {@link android.content.res.ColorStateList} description. + * a color or complex {@link android.content.res.ColorStateList} + * description. + * <p> + * This method will return {@code null} if the attribute is not defined or + * is not an integer color or color state list. * * @param index Index of attribute to retrieve. * - * @return ColorStateList for the attribute, or null if not defined. + * @return ColorStateList for the attribute, or {@code null} if not + * defined. + * @throws RuntimeException if the attribute if the TypedArray has already + * been recycled. + * @throws UnsupportedOperationException if the attribute is defined but is + * not an integer color or color state list. */ + @Nullable public ColorStateList getColorStateList(int index) { if (mRecycled) { throw new RuntimeException("Cannot make calls to a recycled instance!"); @@ -422,7 +477,8 @@ public class TypedArray { final TypedValue value = mValue; if (getValueAt(index*AssetManager.STYLE_NUM_ENTRIES, value)) { if (value.type == TypedValue.TYPE_ATTRIBUTE) { - throw new RuntimeException("Failed to resolve attribute at index " + index); + throw new UnsupportedOperationException( + "Failed to resolve attribute at index " + index); } return mResources.loadColorStateList(value, value.resourceId, mTheme); } @@ -431,12 +487,18 @@ public class TypedArray { /** * Retrieve the integer value for the attribute at <var>index</var>. + * <p> + * Unlike {@link #getInt(int, int)}, this method will throw an exception if + * the attribute is defined but is not an integer. * * @param index Index of attribute to retrieve. * @param defValue Value to return if the attribute is not defined or * not a resource. * * @return Attribute integer value, or defValue if not defined. + * @throws RuntimeException if the TypedArray has already been recycled. + * @throws UnsupportedOperationException if the attribute is defined but is + * not an integer. */ public int getInteger(int index, int defValue) { if (mRecycled) { @@ -449,10 +511,11 @@ public class TypedArray { if (type == TypedValue.TYPE_NULL) { return defValue; } else if (type >= TypedValue.TYPE_FIRST_INT - && type <= TypedValue.TYPE_LAST_INT) { + && type <= TypedValue.TYPE_LAST_INT) { return data[index+AssetManager.STYLE_DATA]; } else if (type == TypedValue.TYPE_ATTRIBUTE) { - throw new RuntimeException("Failed to resolve attribute at index " + index); + throw new UnsupportedOperationException( + "Failed to resolve attribute at index " + index); } throw new UnsupportedOperationException("Can't convert to integer: type=0x" @@ -460,17 +523,23 @@ public class TypedArray { } /** - * Retrieve a dimensional unit attribute at <var>index</var>. Unit + * Retrieve a dimensional unit attribute at <var>index</var>. Unit * conversions are based on the current {@link DisplayMetrics} * associated with the resources this {@link TypedArray} object * came from. + * <p> + * This method will throw an exception if the attribute is defined but is + * not a dimension. * * @param index Index of attribute to retrieve. * @param defValue Value to return if the attribute is not defined or * not a resource. * * @return Attribute dimension value multiplied by the appropriate - * metric, or defValue if not defined. + * metric, or defValue if not defined. + * @throws RuntimeException if the TypedArray has already been recycled. + * @throws UnsupportedOperationException if the attribute is defined but is + * not an integer. * * @see #getDimensionPixelOffset * @see #getDimensionPixelSize @@ -487,9 +556,10 @@ public class TypedArray { return defValue; } else if (type == TypedValue.TYPE_DIMENSION) { return TypedValue.complexToDimension( - data[index+AssetManager.STYLE_DATA], mMetrics); + data[index + AssetManager.STYLE_DATA], mMetrics); } else if (type == TypedValue.TYPE_ATTRIBUTE) { - throw new RuntimeException("Failed to resolve attribute at index " + index); + throw new UnsupportedOperationException( + "Failed to resolve attribute at index " + index); } throw new UnsupportedOperationException("Can't convert to dimension: type=0x" @@ -502,13 +572,19 @@ public class TypedArray { * {@link #getDimension}, except the returned value is converted to * integer pixels for you. An offset conversion involves simply * truncating the base value to an integer. + * <p> + * This method will throw an exception if the attribute is defined but is + * not a dimension. * * @param index Index of attribute to retrieve. * @param defValue Value to return if the attribute is not defined or * not a resource. * * @return Attribute dimension value multiplied by the appropriate - * metric and truncated to integer pixels, or defValue if not defined. + * metric and truncated to integer pixels, or defValue if not defined. + * @throws RuntimeException if the TypedArray has already been recycled. + * @throws UnsupportedOperationException if the attribute is defined but is + * not an integer. * * @see #getDimension * @see #getDimensionPixelSize @@ -525,9 +601,10 @@ public class TypedArray { return defValue; } else if (type == TypedValue.TYPE_DIMENSION) { return TypedValue.complexToDimensionPixelOffset( - data[index+AssetManager.STYLE_DATA], mMetrics); + data[index + AssetManager.STYLE_DATA], mMetrics); } else if (type == TypedValue.TYPE_ATTRIBUTE) { - throw new RuntimeException("Failed to resolve attribute at index " + index); + throw new UnsupportedOperationException( + "Failed to resolve attribute at index " + index); } throw new UnsupportedOperationException("Can't convert to dimension: type=0x" @@ -541,13 +618,19 @@ public class TypedArray { * integer pixels for use as a size. A size conversion involves * rounding the base value, and ensuring that a non-zero base value * is at least one pixel in size. + * <p> + * This method will throw an exception if the attribute is defined but is + * not a dimension. * * @param index Index of attribute to retrieve. * @param defValue Value to return if the attribute is not defined or * not a resource. * * @return Attribute dimension value multiplied by the appropriate - * metric and truncated to integer pixels, or defValue if not defined. + * metric and truncated to integer pixels, or defValue if not defined. + * @throws RuntimeException if the TypedArray has already been recycled. + * @throws UnsupportedOperationException if the attribute is defined but is + * not a dimension. * * @see #getDimension * @see #getDimensionPixelOffset @@ -566,7 +649,8 @@ public class TypedArray { return TypedValue.complexToDimensionPixelSize( data[index+AssetManager.STYLE_DATA], mMetrics); } else if (type == TypedValue.TYPE_ATTRIBUTE) { - throw new RuntimeException("Failed to resolve attribute at index " + index); + throw new UnsupportedOperationException( + "Failed to resolve attribute at index " + index); } throw new UnsupportedOperationException("Can't convert to dimension: type=0x" @@ -578,12 +662,18 @@ public class TypedArray { * {@link android.view.ViewGroup}'s layout_width and layout_height * attributes. This is only here for performance reasons; applications * should use {@link #getDimensionPixelSize}. + * <p> + * This method will throw an exception if the attribute is defined but is + * not a dimension or integer (enum). * * @param index Index of the attribute to retrieve. * @param name Textual name of attribute for error reporting. * * @return Attribute dimension value multiplied by the appropriate - * metric and truncated to integer pixels. + * metric and truncated to integer pixels. + * @throws RuntimeException if the TypedArray has already been recycled. + * @throws UnsupportedOperationException if the attribute is defined but is + * not a dimension or integer (enum). */ public int getLayoutDimension(int index, String name) { if (mRecycled) { @@ -600,10 +690,11 @@ public class TypedArray { return TypedValue.complexToDimensionPixelSize( data[index+AssetManager.STYLE_DATA], mMetrics); } else if (type == TypedValue.TYPE_ATTRIBUTE) { - throw new RuntimeException("Failed to resolve attribute at index " + index); + throw new UnsupportedOperationException( + "Failed to resolve attribute at index " + index); } - throw new RuntimeException(getPositionDescription() + throw new UnsupportedOperationException(getPositionDescription() + ": You must supply a " + name + " attribute."); } @@ -615,10 +706,11 @@ public class TypedArray { * * @param index Index of the attribute to retrieve. * @param defValue The default value to return if this attribute is not - * default or contains the wrong type of data. + * default or contains the wrong type of data. * * @return Attribute dimension value multiplied by the appropriate - * metric and truncated to integer pixels. + * metric and truncated to integer pixels. + * @throws RuntimeException if the TypedArray has already been recycled. */ public int getLayoutDimension(int index, int defValue) { if (mRecycled) { @@ -633,14 +725,14 @@ public class TypedArray { return data[index+AssetManager.STYLE_DATA]; } else if (type == TypedValue.TYPE_DIMENSION) { return TypedValue.complexToDimensionPixelSize( - data[index+AssetManager.STYLE_DATA], mMetrics); + data[index + AssetManager.STYLE_DATA], mMetrics); } return defValue; } /** - * Retrieve a fractional unit attribute at <var>index</var>. + * Retrieves a fractional unit attribute at <var>index</var>. * * @param index Index of attribute to retrieve. * @param base The base value of this fraction. In other words, a @@ -652,7 +744,10 @@ public class TypedArray { * not a resource. * * @return Attribute fractional value multiplied by the appropriate - * base value, or defValue if not defined. + * base value, or defValue if not defined. + * @throws RuntimeException if the TypedArray has already been recycled. + * @throws UnsupportedOperationException if the attribute is defined but is + * not a fraction. */ public float getFraction(int index, int base, int pbase, float defValue) { if (mRecycled) { @@ -668,7 +763,8 @@ public class TypedArray { return TypedValue.complexToFraction( data[index+AssetManager.STYLE_DATA], base, pbase); } else if (type == TypedValue.TYPE_ATTRIBUTE) { - throw new RuntimeException("Failed to resolve attribute at index " + index); + throw new UnsupportedOperationException( + "Failed to resolve attribute at index " + index); } throw new UnsupportedOperationException("Can't convert to fraction: type=0x" @@ -676,7 +772,7 @@ public class TypedArray { } /** - * Retrieve the resource identifier for the attribute at + * Retrieves the resource identifier for the attribute at * <var>index</var>. Note that attribute resource as resolved when * the overall {@link TypedArray} object is retrieved. As a * result, this function will return the resource identifier of the @@ -688,6 +784,7 @@ public class TypedArray { * not a resource. * * @return Attribute resource identifier, or defValue if not defined. + * @throws RuntimeException if the TypedArray has already been recycled. */ public int getResourceId(int index, int defValue) { if (mRecycled) { @@ -706,13 +803,15 @@ public class TypedArray { } /** - * Retrieve the theme attribute resource identifier for the attribute at + * Retrieves the theme attribute resource identifier for the attribute at * <var>index</var>. * * @param index Index of attribute to retrieve. * @param defValue Value to return if the attribute is not defined or not a - * resource. + * resource. + * * @return Theme attribute resource identifier, or defValue if not defined. + * @throws RuntimeException if the TypedArray has already been recycled. * @hide */ public int getThemeAttributeId(int index, int defValue) { @@ -730,10 +829,16 @@ public class TypedArray { /** * Retrieve the Drawable for the attribute at <var>index</var>. + * <p> + * This method will throw an exception if the attribute is defined but is + * not a color or drawable resource. * * @param index Index of attribute to retrieve. * - * @return Drawable for the attribute, or null if not defined. + * @return Drawable for the attribute, or {@code null} if not defined. + * @throws RuntimeException if the TypedArray has already been recycled. + * @throws UnsupportedOperationException if the attribute is defined but is + * not a color or drawable resource. */ @Nullable public Drawable getDrawable(int index) { @@ -744,7 +849,8 @@ public class TypedArray { final TypedValue value = mValue; if (getValueAt(index*AssetManager.STYLE_NUM_ENTRIES, value)) { if (value.type == TypedValue.TYPE_ATTRIBUTE) { - throw new RuntimeException("Failed to resolve attribute at index " + index); + throw new UnsupportedOperationException( + "Failed to resolve attribute at index " + index); } return mResources.loadDrawable(value, value.resourceId, mTheme); } @@ -756,10 +862,15 @@ public class TypedArray { * This gets the resource ID of the selected attribute, and uses * {@link Resources#getTextArray Resources.getTextArray} of the owning * Resources object to retrieve its String[]. + * <p> + * This method will throw an exception if the attribute is defined but is + * not a text array resource. * * @param index Index of attribute to retrieve. * - * @return CharSequence[] for the attribute, or null if not defined. + * @return CharSequence[] for the attribute, or {@code null} if not + * defined. + * @throws RuntimeException if the TypedArray has already been recycled. */ public CharSequence[] getTextArray(int index) { if (mRecycled) { @@ -780,7 +891,8 @@ public class TypedArray { * @param outValue TypedValue object in which to place the attribute's * data. * - * @return Returns true if the value was retrieved, else false. + * @return {@code true} if the value was retrieved, false otherwise. + * @throws RuntimeException if the TypedArray has already been recycled. */ public boolean getValue(int index, TypedValue outValue) { if (mRecycled) { @@ -794,7 +906,9 @@ public class TypedArray { * Returns the type of attribute at the specified index. * * @param index Index of attribute whose type to retrieve. + * * @return Attribute type. + * @throws RuntimeException if the TypedArray has already been recycled. */ public int getType(int index) { if (mRecycled) { @@ -814,6 +928,7 @@ public class TypedArray { * @param index Index of attribute to retrieve. * * @return True if the attribute has a value, false otherwise. + * @throws RuntimeException if the TypedArray has already been recycled. */ public boolean hasValue(int index) { if (mRecycled) { @@ -834,6 +949,7 @@ public class TypedArray { * @param index Index of attribute to retrieve. * * @return True if the attribute has a value or is empty, false otherwise. + * @throws RuntimeException if the TypedArray has already been recycled. */ public boolean hasValueOrEmpty(int index) { if (mRecycled) { @@ -857,6 +973,7 @@ public class TypedArray { * @return Returns a TypedValue object if the attribute is defined, * containing its data; otherwise returns null. (You will not * receive a TypedValue whose type is TYPE_NULL.) + * @throws RuntimeException if the TypedArray has already been recycled. */ public TypedValue peekValue(int index) { if (mRecycled) { @@ -872,6 +989,9 @@ public class TypedArray { /** * Returns a message about the parser state suitable for printing error messages. + * + * @return Human-readable description of current parser state. + * @throws RuntimeException if the TypedArray has already been recycled. */ public String getPositionDescription() { if (mRecycled) { @@ -882,8 +1002,10 @@ public class TypedArray { } /** - * Recycle the TypedArray, to be re-used by a later caller. After calling + * Recycles the TypedArray, to be re-used by a later caller. After calling * this function you must not ever touch the typed array again. + * + * @throws RuntimeException if the TypedArray has already been recycled. */ public void recycle() { if (mRecycled) { @@ -905,9 +1027,10 @@ public class TypedArray { * Removes the entries from the typed array so that subsequent calls to typed * getters will return the default value without crashing. * - * @return An array of length {@link #getIndexCount()} populated with theme - * attributes, or {@code null} if there are no theme attributes in - * the typed array. + * @return an array of length {@link #getIndexCount()} populated with theme + * attributes, or null if there are no theme attributes in the typed + * array + * @throws RuntimeException if the TypedArray has already been recycled. * @hide */ @Nullable @@ -966,9 +1089,14 @@ public class TypedArray { * * @return Returns a mask of the changing configuration parameters, as * defined by {@link android.content.pm.ActivityInfo}. + * @throws RuntimeException if the TypedArray has already been recycled. * @see android.content.pm.ActivityInfo */ public int getChangingConfigurations() { + if (mRecycled) { + throw new RuntimeException("Cannot make calls to a recycled instance!"); + } + int changingConfig = 0; final int[] data = mData; |