Reputation: 3253
I am using the @Retention
and @StringDef
annotations for some of my methods in a library and I face a strange warning, I want to understand.
In a static class, SIP
, I use this annotation:
public static final String CODEC_SPEEX_16K = "speex/16000/1";
public static final String CODEC_SPEEX_8K = "speex/8000/1";
public static final String CODEC_SPEEX_32K = "speex/32000/1";
public static final String CODEC_ILBC_8K = "iLBC/8000/1";
public static final String CODEC_GSM_8K = "GSM/8000/1";
public static final String CODEC_PCMU_8K = "PCMU/8000/1";
public static final String CODEC_PCMA_8K = "PCMA/8000/1";
public static final String CODEC_G722_16K = "G722/16000/1";
@Retention(RetentionPolicy.CLASS)
@StringDef({
CODEC_SPEEX_16K,
CODEC_SPEEX_8K,
CODEC_SPEEX_32K,
CODEC_ILBC_8K,
CODEC_GSM_8K,
CODEC_PCMU_8K,
CODEC_PCMA_8K,
CODEC_G722_16K
})
public @interface CodecName {}
which compiles fine, without any warnings.
In the static class Tools
I use this annotation:
public static final String RES_TYPE_STRING = "string";
public static final String RES_TYPE_DRAWABLE = "drawable";
public static final String RES_TYPE_LAYOUT = "layout";
public static final String RES_TYPE_VIEW = "id";
public static final String RES_TYPE_DIMEN = "dimen";
public static final String RES_TYPE_COLOR = "color";
public static final String RES_TYPE_ANIM = "anim";
public static final String RES_TYPE_MIPMAP = "mipmap";
@Retention(RetentionPolicy.CLASS)
@StringDef({
RES_TYPE_STRING,
RES_TYPE_DRAWABLE,
RES_TYPE_LAYOUT,
RES_TYPE_DIMEN,
RES_TYPE_COLOR,
RES_TYPE_ANIM,
RES_TYPE_VIEW,
RES_TYPE_MIPMAP
})
public @interface ResourceType {
}
and I get the warning:
The typedef annotation ....toolbox.Tools.ResourceType should have @Retention(RetentionPolicy.SOURCE)
It seems to be uncritical, everything works fine. But can someone please explain me, why
Annotation#1 does not get a warning ;
Annotation#2 gets a warning;
Both are built identical, both only used in static context. From my point of view, both are the same.
Upvotes: 22
Views: 3173
Reputation: 1084
Typedef annotations Typedef annotations check whether a particular parameter, return value, or field references a specific set of constants. They also enable code completion to automatically offer the allowed constants.
Use the @IntDef and @StringDef annotations to create enumerated annotations of integer and string sets to validate other types of code references.
Typedef annotations use @interface to declare the new enumerated annotation type. The @IntDef and @StringDef annotations, along with @Retention, annotate the new annotation and are necessary to define the enumerated type. The @Retention(RetentionPolicy.SOURCE) annotation tells the compiler not to store the enumerated annotation data in the .class file.
The following example shows the steps to create an annotation that checks whether a value passed as a method parameter references one of the defined constants:
import androidx.annotation.IntDef
//...
// Define the list of accepted constants and declare the NavigationMode annotation.
@Retention(AnnotationRetention.SOURCE)
@IntDef(NAVIGATION_MODE_STANDARD, NAVIGATION_MODE_LIST, NAVIGATION_MODE_TABS)
annotation class NavigationMode
// Declare the constants.
const val NAVIGATION_MODE_STANDARD = 0
const val NAVIGATION_MODE_LIST = 1
const val NAVIGATION_MODE_TABS = 2
abstract class ActionBar {
// Decorate the target methods with the annotation.
// Attach the annotation.
@get:NavigationMode
@setparam:NavigationMode
abstract var navigationMode: Int
}
When you build this code, a warning is generated if the mode parameter doesn't reference one of the defined constants (NAVIGATION_MODE_STANDARD, NAVIGATION_MODE_LIST, or NAVIGATION_MODE_TABS).
Combine @IntDef and @IntRange to indicate that an integer can be either a given set of constants or a value within a range.
Upvotes: 0