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
        }

2