上一篇博文中简单介绍了 Android Annotations 的基本用法,顺便扯了一下概念 - 契约编程,阅读量少的可怜,看来并没有多少人对此感兴趣,今天再来一篇,介绍几个稍微高级点的用法,我就不信弄不出一个大新闻。
本篇将要介绍的几个也许并不常用,但是逼格是有保证的,它们是
- Thread Annotations
 - CheckResult Annotations
 - CallSuper Annotations
 - Enumerated Annotations
 
Thread Annotations
Thread Annotations 有四位成员 - @UiThread、@MainThread、@WorkerThread、@BinderThread,它们来自不同的 java 文件,却拥有着共同的 target,不信你看:
@Retention(CLASS)
@Target({METHOD,CONSTRUCTOR,TYPE})
 
如果标记 class,那么这个 class 的所有方法都必须在指定线程上执行,例如
@UiThread
public class NavigationBar {
  @NonNull
  private NavigationBar addEntry(
    @StringRes int iconFontRes, 
    @NonNull String title,
    @NonNull OnClickListener listener) {
    // ...
  }
  // ...
}
 
这样一来,NavigationBar 的所有方法都要运行在 Ui Thread,否则 Android Studio 会!报!错!
@MainThread 与 @UiThread 的区别比较微妙,首先放放链接 - Support Annotations。总结起来一句话:@MainThread 用于标记与生命周期相关的方法,@UiThread 用于 View Hierarchy,但是 Android Studio 认为两者是可以互换的,所以有这两种标记的方法可以互相调用。
然后我再稍微补充几句:
一个进程有且只有一个主线程 - @MainThread,同时它也是一个 @UiThread。例如,activity 的 main window 就运行在 @MainThread 上,但是系统也允许应用创建其他的线程以运行不同的 window(除了系统进程会这么干,几乎没有其他场景)
@CheckResult
这个 Annotation 对于【只看方法名无法判断是否有返回值】的方法特别管用,例如:
public boolean openUp()
 
只看方法名openUp,可能不会多想,调用一下就完事了,也不会判断返回值。
 但是如果必须要判断 openUp 的返回值,除了文档约束好像也没有其他办法,有了 @CheckResults,一切都变得简单明了。

@CallSuper
如果你提供了 api 给别人用,但是这个 api 必须要先调用父类方法才能正确执行,怎么办?让 @CallSuper 来拯救你。

Enumerated Annotations
编写高性能代码,从不用 enum 开始!
每一个 enum 都是一个对象,无论从内存还是从性能上来看,都没有一个 primitive type 的变量效率高。
例如,定义一个类 - ActionBar,用户可以通过 setMode 设置不同的模式,如果使用 enum,可能会写成下面这样:
public class ActionBar {
    public enum Theme {
        DARK, LIGHT
    }
    private Theme mTheme;
    public void setTheme(Theme theme) {
        mTheme = theme;
    }
}
 
为了提升代码效率,可以用两个整形变量来替代 Theme,但是这样无法保证参数 theme 的合法性,用户可能传入了 DARK 和 LIGHT 之外的值。
public class ActionBar {
    public static final int DARK = 0x00;
    public static final int LIGHT = 0x01;
    private int mTheme;
    public void setTheme(int theme) {
        mTheme = theme;
    }
}
 
如何既能提升效率又可以保证传入参数的合法性呢?
 用 @IntDef 来添加一个约束就搞定了。
public class ActionBar {
    @IntDef({DARK, LIGHT})
    @Retention(RetentionPolicy.SOURCE)
    public @interface Theme {}
    public static final int DARK = 0x00;
    public static final int LIGHT = 0x01;
    private int mTheme;
    public void setTheme(@Theme int theme) {
        mTheme = theme;
    }
    @Theme
    public int getTheme() {
        return mTheme;
    }
}
 
如果用户调用 setTheme 时传入了非法参数,Android Studio 会!报!错!

如果我们打算把 DARK 和 LIGHT 作为一个 flag,允许用户通过逻辑运算去自由组合,也就说可以这样调用 setTheme。
setTheme(DARK | LIGHT);
setTheme(DARK & LIGHT);
 
只需要把 @IntDef 的 flag 属性设为 true 即可。
public class ActionBar {
    @IntDef(flag = true, value = {DARK, LIGHT})
    @Retention(RetentionPolicy.SOURCE)
    public @interface Theme {}
    public static final int DARK = 0x00;
    public static final int LIGHT = 0x01;
    private int mTheme;
    public void setTheme(@Theme int theme) {
        mTheme = theme;
    }
    @Theme
    public int getTheme() {
        return mTheme;
    }
}
 
@StringDef 与 @IntDef 的原理一样,只不过用到的常量是 String 类型。
参考资料
- http://anupcowkur.com/posts/a-look-at-android-support-annotations/
 - http://developer.android.com/tools/debugging/annotations.html
 
                  
                  
                  
                  
本文深入探讨AndroidAnnotations的高级用法,包括ThreadAnnotations、CheckResultAnnotations、CallSuperAnnotations和EnumeratedAnnotations,旨在帮助开发者掌握更复杂的编程技巧,提高代码质量和效率。
          
      
          
                
                
                
                
              
                
                
                
                
                
              
                
                
              
            
                  
					1170
					
被折叠的  条评论
		 为什么被折叠?
		 
		 
		
    
  
    
  
            


            