0 前言
Android源码可以说是Android开发的最佳实践代码,所以从Android源码中,可以学习怎样写出优秀的代码。
1 @StringDef和@IntDef的使用
@StringDef和@IntDef可以用来代替枚举使用。
Context.getSystemService方法中,就使用了@StringDef。
/** @hide */
@StringDef(suffix = { "_SERVICE" }, value = {
POWER_SERVICE,
WINDOW_SERVICE,
......
PERMISSION_SERVICE,
LIGHTS_SERVICE,
})
@Retention(RetentionPolicy.SOURCE)
public @interface ServiceName {}
public abstract @Nullable Object getSystemService(@ServiceName @NonNull String name);
当调用函数时,被@ServiceName修饰的参数,只能从定义的范围里面选择,否则编译器会做相关提示,但也是可以运行的。
@IntDef用法类似,用来修饰int值。
在ContextImpl类中有如下代码
static final int STATE_UNINITIALIZED = 0;
static final int STATE_INITIALIZING = 1;
static final int STATE_READY = 2;
static final int STATE_NOT_FOUND = 3;
/** @hide */
@IntDef(prefix = { "STATE_" }, value = {
STATE_UNINITIALIZED,
STATE_INITIALIZING,
STATE_READY,
STATE_NOT_FOUND,
})
@Retention(RetentionPolicy.SOURCE)
@interface ServiceInitializationState {}
说一个题外话,记得刚做Android开发时就听说不要使用enum枚举,因为枚举比静态常量多两倍以上的内存,所以一直都不敢在开发时使用枚举,但是在写@StringDef和@IntDef代替枚举相关内容时,偶然发现一篇文章介绍android中的枚举的,Android 中不应该使用 Enum 吗?,然后也去看了下lifecycle的源码,确实是使用了enum。所以枚举没那么恐怖,以后就放心的使用枚举吧。
//lifecycle部分源码
@SuppressWarnings("WeakerAccess")
public enum Event {
/**
* Constant for onCreate event of the {@link LifecycleOwner}.
*/
ON_CREATE,
/**
* Constant for onStart event of the {@link LifecycleOwner}.
*/
ON_START,
/**
* Constant for onResume event of the {@link LifecycleOwner}.
*/
ON_RESUME,
/**
* Constant for onPause event of the {@link LifecycleOwner}.
*/
ON_PAUSE,
/**
* Constant for onStop event of the {@link LifecycleOwner}.
*/
ON_STOP,
/**
* Constant for onDestroy event of the {@link LifecycleOwner}.
*/
ON_DESTROY,
/**
* An {@link Event Event} constant that can be used to match all events.
*/
ON_ANY
}
androidx下的RecyclerView的源码里面,也使用了枚举
//RecyclerView line 7823
/**
* Defines how this Adapter wants to restore its state after a view reconstruction (e.g.
* configuration change).
*/
public enum StateRestorationPolicy {
/**
* Adapter is ready to restore State immediately, RecyclerView will provide the state
* to the LayoutManager in the next layout pass.
*/
ALLOW,
/**
* Adapter is ready to restore State when it has more than 0 items. RecyclerView will
* provide the state to the LayoutManager as soon as the Adapter has 1 or more items.
*/
PREVENT_WHEN_EMPTY,
/**
* RecyclerView will not restore the state for the Adapter until a call to
* {@link #setStateRestorationPolicy(StateRestorationPolicy)} is made with either
* {@link #ALLOW} or {@link #PREVENT_WHEN_EMPTY}.
*/
PREVENT
}