您的位置:首页 > 移动开发 > Android开发

怎样用 Android Annotations 写出高性能代码

2015-11-09 17:49 363 查看
上一篇博文中简单介绍了 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

版权声明:本文为博主原创文章,未经博主允许不得转载。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: