AndroidAnnotations详解

几年前整理的攻略,放上来自己消化。

AndroidAnnotations是一个能够让你快速进行Android开发的开源注解框架,相比原生的android开发,它能够帮助你减少大量的重复代码,将精力集中于真正精髓的部分,降低代码冗余,提高代码可维护性。框架的机制类似于java spring框架中的IOCjar包小,功能强大,使用非常方便。

对于使用了 AndroidAnnotations的代码和原生代码的区别,举最简单的例子来看:

布局文件

[html] view plaincopy

  

  
  

 

这个布局文件中可以看到只有最简单的几个常用控件,那么使用普通代码初始化赋值如下:

普通代码

[java] view plaincopy

1. public class MainActivity extends Activity {  

2.    

3.     EditText et;  

4.     TextView tv;  

5.     Button btn;  

6.    

7.     @Override  

8.     protected void onCreate(Bundle savedInstanceState) {  

9.        super.onCreate(savedInstanceState);  

10.        setContentView(R.layout.activity_main);  

11.    

12.        et = (EditText) findViewById(R.id.et);  

13.        tv = (TextView) findViewById(R.id.tv);  

14.        btn = (Button) findViewById(R.id.btn);  

15.    

16.        btn.setOnClickListener(new OnClickListener() {  

17.    

18.            @Override  

19.            public void onClick(View v) {  

20.               tv.setText("Content:" +et.getText());  

21.            }  

22.        });  

23.    

24.     }  

25. }  

而使用AndroidAnnotations的代码则结果如下

Annotations代码

[java] view plaincopy

1. @EActivity(R.layout.activity_main)  

2. public class MainActivity extends Activity {  

3.    

4.     @ViewById  

5.     EditText et;  

6.     @ViewById  

7.     TextView tv;  

8.    

9.     @Click  

10.     void btn() {  

11.        tv.setText("Content:" +et.getText());  

12.     }  

13.    

14. }  

可以看到单从行数上来说,代码量几乎是减少了一半,这对开发来讲效率和维护性的提高都是非常明显的。

在上面的代码中我们可以看到使用了@EActivity@ViewById@Click三个annotation(注解),当然它还提供了其他很多annotation单单就代码里面这几个来说首先@EActivity后必须要有一个layout id 来表示这个Activity所使用的布局,来的onCreate方法就不需要再用了,这样可以让我们少写一些代码,@ViewById就和原来的findViewById()方法一样。

值得注意的是:@ViewById后的id是可以不写的,但是要求控件变量名称要与xml中定义的id一致,也就是说,当我在xml文件中定义的TextViewid必须是:android:id="@+id/textView" . 这样我们在@ViewById后就不用再写括号了,直接写

[html] view plaincopyprint?

1. @ViewById  

2. TextView textView;  


就可以了。但是这样会有一个问题,运行时会报出:NullPointerException空指针异常,我们就不能在myButton()方法中直接使用,而是要加上@AfterView注解。

[java] view plaincopyprint?

1. @AfterView  

2. void init(){  

3.     textView.setText("Hello");  

4. }  


这样就不会有问题了。对于@Click,方法名和xml文件中的id一样就可以这样写,AndroidAnnotations会自动识别,对于

多个Button,可以写多个@Click比如这样

[java] view plaincopyprint?

1. @Click({R.id.button1,R.id.button2,R.id.button3})  

2. void buttonClicked(Button bt){  

3.     switch(bt.getId()){  

4.     case R.id.button1:  //  

5.         break;  

6.         ...  

7.     }  

8. }  

至于xml文件,还是和之前一样。

需要注意的一点就是:使用AndroidAnnotations千万要记得,编译的时候会生成一个子类,这个子类的名称就是在原来的类之后加了一个下划线“_”,比如这个例子产生的子类名称为“MyActivity_”,这就需要你在注册这个Activity的时候,在AndroidManifest.xml中将MyActivity改为MyActivity_,使用的时候也是使用MyActivity_来表示此类,如从另一个Activity跳转到此界面就要这样用:

[java] view plaincopyprint?

1. startActivity(new Intent(this,MyActivity_.class));  


注意,是MyActivity_.class不是MyActivity.class;

 

以下是我整理出来的初次使用annotations的方法:

 

AndroidAnnotations部署

 

环境:

系统:windows 8.164bit

开发工具:Eclipse 3.8

JDK版本:jdk1.6

构建工具:AntEclipse默认的build tool

androidannotations2.7

 

步骤:

1. 下载并导入jar

2. 配置Ant

3. 配置Eclipse

 

1.  jar包官网下载地址https://github.com/excilys/androidannotations/wiki/Download;

解压后的两个jarandroidannotations-api-2.7.1.jarandroidannotations-2.7.1.jar分别放在项目的libs文件夹下和compile-libs文件夹下(compile-libs需要自己创建,创建在项目的根目录下就行。如果放在了同一文件夹下必然出错,因为两个包里存在相同的文件路径和文件名)。

 

2. 配置Ant只需要在项目的根目录下创建两个文件即可(build.xmlcustom_rules.xml

创建build.xml使用cmd命令

[plain] view plaincopy

1. android update project --path "$PROJECT_ROOT$"  

如果没有配置android环境变量要进入到..\sdk\tools\目录下去执行,"$PROJECT_ROOT$"为项目的根路径,例如:

D:\Program Files\adt-bundle-windows-x86_64\sdk\tools>android update project --path F:\work_in_geekon\workspace\TestAA

至于custom_rules.xml手动创建即可,首先添加如下内容

[html] view plaincopy

1. <propertynamepropertyname="generated.dir"value=".apt_generated"/>  

2. <propertynamepropertyname="generated.absolute.dir"location="${generated.dir}"/>  

3. propertyname="java.compilerargs"value="-s'${generated.absolute.dir}'"/>  

4. <targetnametargetname="-pre-compile">  

5.       mkdirdir="${generated.absolute.dir}"/>  

6.   

打开$ANDROID_SDK_ROOT$/tools/ant/build.xml(例如我的D:\ProgramFiles\adt-bundle-windows-x86_64\sdk\tools\ant\build.xml),找到节点

[html] view plaincopy

1. <targetnametargetname="-compile"depends="-build-setup, -pre-build, -code-gen, -pre-compile">  

2.  ...  

3.   

将上述内容全部copycustom_rules.xml中。找到以下节点(在custom_rules.xml文件中),并添加

[html] view plaincopy

1.  dir="compile-libs"includes="*.jar"/>  


...
           
                ...
               
           
...

绿色部分为新增内容。保存文件,Ant的配置也就OK了。

 

3. 配置Eclipse

选择项目右键,Properties à Java Compiler ,确保编译器版本为1.6及以上

Properties >> Java Compiler >> Annotation Processing >> Enable annotation processing(开启)

Properties >> Java Compiler >> Annotation Processing >> Factory Path >>添加jar包,就是之前放在compile-libs目录下的androidannotations-2.7.1.jar

重新编译(Clean)下项目既可以了。

 

注意:AndroidManifest.xml文件里的ActivityApplication的名字都要在原来的基础上加一个下划线(”_”。例如

<activityandroid:name="com.example.testaa.MainActivity">

activity>

改成

<activityandroid:name="com.example.testaa.MainActivity_">activity>

Activity跳转的时候也要如此new Intent().setClass(this, MainActivity_.class);

 

 

此处再附上另外一种配置方法

项目中重要的两个jar包分别是:androidannotations-api-3.0.1.jar和androidannotations-3.0.1.jar

    2.新建一个android项目,然后将androidannotations-api-3.0.1.jar复制到libs目录下,在项目的根目录新建一个文件夹,命名为compile-libs,然后将androidannotations-3.0.1.jar复制到该目录下

    3.然后设置项目属性:右键->Properties->Java Compiler->Annotation Processing 在该页面选中Enable project specific settings。

 

    然后点击Annotation Processing的子项Factory Path页面,选中Enable project specific settings,然后添加编译所需的jar包。点击“Add JARs”将之前complie-libs目录下的androidannotations-3.0.1.jar导入,保存后退出。

    

 

一些常用Annotations注释的使用方法:
@AfterInject  定义的方法在类的构造方法执行后执行
@AfterTextChange  定义的方法在TextView及其子类的Text属性改变后执行
@AfterViews  定义的方法在setContentView后执行
@Background  定义的方法在后台线程执行,开启的线程在线程池中管理
@BeforeTextChange  定义的方法在TextView及其子类的Text属性改变前执行
@Click  定义点击监听器
@EActivity  Activity中启用Annotations
@EProvider  ContentProvider中启用Annotations
@EReceive  BroadcastReceiver中启用Annotations
@Eservice  Service中启用Annotations
@EView  在自定义的View的子类中启用Annotations
@Fullscreen  全屏

@NoTitle   无标题栏

@Extra  含义和getIntent().getExtra()相同,目的是获取上一个Activity通过Intent传递过来的值。

 

附上Github上对可用的annotations列表总结地址(点击每一个均有详细的注解):

https://github.com/excilys/androidannotations/wiki/AvailableAnnotations

 

补充说明:

    1,onSaveInstanceState的使用
        保存activity暂时的状态(保存类成员变量关联着UI的值,例如:某个处于选中状态下RadioButton的ID),
        便于恢复
    2,使用@EBean的JavaBean,能直接取到调用他的Context,并且支持@ViewById标签找到控件,因此,
       构造方法传过来的参数可以少很多。

 

 

附上一段使用annotations注解类型较多的代码供参考:

1. package com.googlecode.androidannotations.helloworldeclipse;

2. 

3. import java.util.Date;

4. import java.util.concurrent.TimeUnit;

5. 

6. import android.app.Activity;

7. import android.app.Notification;

8. import android.app.NotificationManager;

9. import android.app.PendingIntent;

10. import android.content.Intent;

11. import android.database.sqlite.SQLiteDatabase;

12. import android.os.Bundle;

13. import android.util.Log;

14. import android.view.MotionEvent;

15. import android.view.View;

16. import android.view.Window;

17. import android.view.WindowManager;

18. import android.widget.EditText;

19. import android.widget.TextView;

20. import android.widget.Toast;

21. 

22. import com.googlecode.androidannotations.annotations.Background;

23. import com.googlecode.androidannotations.annotations.Click;

24. import com.googlecode.androidannotations.annotations.EActivity;

25. import com.googlecode.androidannotations.annotations.LongClick;

26. import com.googlecode.androidannotations.annotations.SystemService;

27. import com.googlecode.androidannotations.annotations.Touch;

28. import com.googlecode.androidannotations.annotations.Transactional;

29. import com.googlecode.androidannotations.annotations.UiThread;

30. import com.googlecode.androidannotations.annotations.ViewById;

31. import com.googlecode.androidannotations.annotations.res.BooleanRes;

32. import com.googlecode.androidannotations.annotations.res.ColorRes;

33. import com.googlecode.androidannotations.annotations.res.StringRes;

34. 

35. @EActivity(R.layout.my_activity) //布局文件在这里声明,不用在setContentView

36. public class MyActivity extends Activity {

37. 

38.     @ViewById //控件这样标注,由于是IOC模式,因此不需要自己实例化

39.     EditText myEditText;

40. 

41.     @ViewById(R.id.myTextView) //提供id来生成控件,如果不指定ID,默认以控件名进行查找,如上面的myEditText

42.     TextView textView;

43. 

44.     @StringRes(R.string.hello) //资源

45.     String helloFormat;

46. 

47.     @ColorRes

48.     int androidColor;

49. 

50.     @BooleanRes

51.     boolean someBoolean;

52. 

53.     @SystemService

54.     NotificationManager notificationManager;

55. 

56.     @SystemService

57.     WindowManager windowManager;

58. 

59.     /**

60.      * AndroidAnnotations gracefully handles support for onBackPressed, whether

61.      * you use ECLAIR (2.0), or pre ECLAIR android version.

62.      */

63.     public void onBackPressed() {

64.         Toast.makeText(this, "Back key pressed!", Toast.LENGTH_SHORT).show();

65.     }

66.     

67.     @Override

68.     protected void onCreate(Bundle savedInstanceState) {

69.         super.onCreate(savedInstanceState);

70.         // windowManager should not be null

71.         windowManager.getDefaultDisplay();

72.         requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);

73.     }

74. 

75. 

76.     @Click //事件控制,可以以按钮的id作为方法名,同时支持的事件还有onLongClickonTextChange

77.     void myButtonClicked() {

78.         String name = myEditText.getText().toString();

79.         setProgressBarIndeterminateVisibility(true);

80.         someBackgroundWork(name, 5);

81.     }

82. 

83.     @Background //开启新线程后台运行,注意不要引用UI控件,而且返回值类型一定是void

84.     void someBackgroundWork(String name, long timeToDoSomeLongComputation) {

85.         try {

86.             TimeUnit.SECONDS.sleep(timeToDoSomeLongComputation);

87.         } catch (InterruptedException e) {

88.         }

89. 

90.         String message = String.format(helloFormat, name);

91. 

92.         updateUi(message, androidColor);

93. 

94.         showNotificationsDelayed();

95.     }

96. 

97.     @UiThread //UI线程

98.     void updateUi(String message, int color) {

99.         setProgressBarIndeterminateVisibility(false);

100.         textView.setText(message);

101.         textView.setTextColor(color);

102.     }

103. 

104.     @UiThread(delay=2000) //可以设置延时时间,以毫秒为单位

105.     void showNotificationsDelayed() {

106.         Notification notification = new Notification(R.drawable.icon, "Hello !", 0);

107.         PendingIntent contentIntent = PendingIntent.getActivity(this, 0, new Intent(), 0);

108.         notification.setLatestEventInfo(getApplicationContext(), "My notification", "Hello World!", contentIntent);

109.         notificationManager.notify(1, notification);

110.     }

111. 

112.     @LongClick

113.     void startExtraActivity() {

114.         Intent intent = new Intent(this, ActivityWithExtra_.class);

115. 

116.         intent.putExtra(ActivityWithExtra.MY_DATE_EXTRA, new Date());

117.         intent.putExtra(ActivityWithExtra.MY_STRING_EXTRA, "hello !");

118.         intent.putExtra(ActivityWithExtra.MY_INT_EXTRA, 42);

119. 

120.         startActivity(intent);

121.     }

122. 

123.     @Click

124.     void startListActivity(View v) {

125.         startActivity(new Intent(this, MyListActivity_.class));

126.     }

127. 

128.     @Touch

129.     void myTextView(MotionEvent event) {

130.         Log.d("MyActivity", "myTextView was touched!");

131.     }

132. 

133.     @Transactional

134.     int transactionalMethod(SQLiteDatabase db, int someParam) {

135.         return 42;

136.     }

137. 

138. }

 

你可能感兴趣的:(AndroidAnnotations详解)