几年前整理的攻略,放上来自己消化。
AndroidAnnotations是一个能够让你快速进行Android开发的开源注解框架,相比原生的android开发,它能够帮助你减少大量的重复代码,将精力集中于真正精髓的部分,降低代码冗余,提高代码可维护性。框架的机制类似于java spring框架中的IOC,jar包小,功能强大,使用非常方便。
对于使用了 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文件中定义的TextView的id必须是: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.1(64bit)
开发工具:Eclipse 3.8
JDK版本:jdk1.6
构建工具:Ant(Eclipse默认的build tool)
androidannotations:2.7
步骤:
1. 下载并导入jar包
2. 配置Ant
3. 配置Eclipse
1. jar包官网下载地址https://github.com/excilys/androidannotations/wiki/Download;
解压后的两个jar包androidannotations-api-2.7.1.jar和androidannotations-2.7.1.jar分别放在项目的libs文件夹下和compile-libs文件夹下(compile-libs需要自己创建,创建在项目的根目录下就行。如果放在了同一文件夹下必然出错,因为两个包里存在相同的文件路径和文件名)。
2. 配置Ant只需要在项目的根目录下创建两个文件即可(build.xml和custom_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.
4. <targetnametargetname="-pre-compile">
5.
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.
将上述内容全部copy到custom_rules.xml中。找到以下节点(在custom_rules.xml文件中),并添加
[html] view plaincopy
1.
...
...
...
绿色部分为新增内容。保存文件,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文件里的Activity和Application的名字都要在原来的基础上加一个下划线(”_”)。例如
<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作为方法名,同时支持的事件还有onLongClick,onTextChange等
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. }