码迷,mamicode.com
首页 > 移动开发 > 详细

AndroidAnnotations用法总结

时间:2015-04-30 12:22:16      阅读:414      评论:0      收藏:0      [点我收藏+]

标签:

开源地址:https://github.com/excilys/androidannotations 
下载下来发现有多种情况下的,编译项目;
eclipse ,gradle,maven环境下;这里主要总结的是在eclipse和gradle编译环境下处理的项目

eclipse环境下配置:

1:配置自动编译注解的环境:(其实这里的配置环境跟ButterKniffe一样配置的)
在默认的情况下,ADT Eclipse项目的Preference中,Java Compiler下没有Annotation Processing;因为要使用开源 androidannotations 注解,发现eclipse没有Annotation Processin
解决办法:

 第一步:先打开Help菜单,点击Install New Software

        技术分享

       第二步,选择安装Juno:

        技术分享

       第三步,在下面的列表中找到Programming Languages节点并展开,找到Eclipse Java Development Tools,勾选上,剩下的安装步骤你懂的,安装完了会要求自动重启Eclipse,重启后就有Annotation Processing啦。

       技术分享

重启后发现就会发现那个配置,

压缩包里包含两个jar文件:androidannotations-x.x.x.jar和androidannotations-api-x.x.x.jar,另外还有个examples文件夹
  • androidannotations-x.x.x.jar是用来提供给java的注解处理插件
  • androidannotations-api-x.x.x.jar是给android工程使用的包

下面用实例里带的HelloWorldEclipse演示如何使用

1. 在eclipse里导入实例工程HelloWorldEclipse
2. 修改HelloWorldEclipse中的lib文件夹为libs,并把androidannotations-api-x.x.x.jar放入目录,回到Eclipse里刷新工程,androidannotations-api-x.x.x.jar被自动引入到了build path
3. 新建一个compilers文件夹,将androidannotations-x.x.x.jar拷贝进来待用
4. 打开工程属性,在Java Build Path-library中的androidannotations-3.1-api.jar删除
5. 打开过程属性,在Java compiler-Annotation Processing中启用Annotation Processing
技术分享
6. 打开过程属性,在Java compiler-Annotation Processing-Factory path中,先删除之前的androidannotations-3.1-api.jar,在把androidannotations-x.x.x.jar(在之前添加的compilers文件夹里)添加进来

技术分享

7. Eclipse会提示重新编译,选择yes,编译成功!注意有时这里不怎么好使,eclipse会反应不过来,可以重启动eclipse,再次clean编译项目;

ant编译情况下:(待研究)


gradle环境下配置:
官方给的Gradle插件我没有测试成功,这个编译脚本是参照了网上的一个脚本写的
  1. buildscript {  
  2.     repositories {  
  3.         mavenLocal()  
  4.         mavenCentral()  
  5.     }    
  6.     dependencies {  
  7.         classpath ‘com.android.tools.build:gradle:0.6.+‘  
  8.         classpath ‘com.googlecode.androidannotations:androidannotations:2.7.1‘  
  9.         classpath ‘com.googlecode.androidannotations:androidannotations-api:2.7.1‘  
  10.     }    
  11. }  
  12.   
  13. repositories {  
  14.     mavenCentral()  
  15. }  
  16.   
  17. apply plugin: ‘android‘  
  18.   
  19. dependencies {  
  20.     compile fileTree(dir: ‘libs‘, include: ‘*.jar‘)    
  21.     compile ‘com.squareup.dagger:dagger-compiler:1.0.1‘  
  22.     compile ‘com.squareup.dagger:dagger:1.0.1‘  
  23.     compile ‘com.squareup:otto:1.3.3‘  
  24. }  
  25.   
  26. android {  
  27.     compileSdkVersion 8  
  28.     buildToolsVersion "19.0.0"  
  29.   
  30.     sourceSets {  
  31.         main {  
  32.             manifest.srcFile ‘AndroidManifest.xml‘  
  33.             res.srcDirs = [‘res‘]  
  34.             assets.srcDirs = [‘assets‘]  
  35.         }  
  36.   
  37.         instrumentTest.setRoot(‘tests‘)  
  38.     }  
  39. }  
  40.   
  41.   
  42. configurations {  
  43.     androidannotations  
  44.     androidannotations.extendsFrom(compile)  
  45. }  
  46.   
  47. dependencies {  
  48.     androidannotations ‘com.googlecode.androidannotations:androidannotations:2.7.1‘  
  49.     compile ‘com.googlecode.androidannotations:androidannotations-api:2.7.1‘  
  50. }  
  51.   
  52.   
  53. android.applicationVariants.each { variant ->  
  54.             variant.javaCompile.classpath += configurations.androidannotations  
  55.             variant.javaCompile.options.compilerArgs += [  
  56.                 ‘-processor‘, ‘com.googlecode.androidannotations.AndroidAnnotationProcessor‘,  
  57.                 ‘-AandroidManifestFile=‘ + variant.processResources.manifestFile  
  58.             ]  
  59. }  

Dagger,ButterKnife,Roboguide,AndroidAnnotations框架的依赖注入浅析
注解框架---AndroidAnnotations这里强调了几点:
AndroidAnnotations简称为AA,大量的使用注解,不会对APP的造成不良影响,会影响到APP的执行性能。
分析主流注解框架:xUtils、ButterKnife、Dragger和Roboguice:
实现原理是一致的,都是通过反射机制实现的,在Runtime运行期去反射类中带有注解的Field和Method,然后再去执行注解相对应的逻辑代码,
这样做:在APP的运行期执行的,会造成执行的效率下降,执行时间变长的缺点。
AA工作的原理:
在编译器中加了一层额外的自动编译步骤,用来生成基于你源码的代码。
使用AA的注解在编译期间就已经自动生成了对应的子类,运行期运行的其实就是这个子类.则不会造成任何负面的影响
总结:从资料的分析来看,AndroidAnnotations像是综合了其他的几个框架的优点,通过注解,减少了繁琐(R.id.btn)的使用,并在编译的时候,将相应的注解进行转换。即:加快了开发的速度,又不影响app的性能。
综合考虑:
Android依赖注入:Dagger、RoboGuice和ButterKnife 这里有三者的比较,但是仅仅是译文,没有一个很好的解释到位。
相反:高手速成android开源项目[tool篇] 这里有很好的解释
AndroidAnnotations特点:
(1) 依赖注入:包括view,extras,系统服务,资源等等
(2) 简单的线程模型,通过annotation表示方法运行在ui线程还是后台线程
(3) 事件绑定:通过annotation表示view的响应事件,不用在写内部类
(4) REST客户端:定义客户端接口,自动生成REST请求的实现
(5) 没有你想象的复杂:AndroidAnnotations只是在在编译时生成相应子类
(6) 不影响应用性能:仅50kb,在编译时完成,不会对运行时有性能影响。
PS:AndroidAnnotations与roboguice的比较:
roboguice通过运行时读取annotations进行反射,所以可能影响应用性能,而AndroidAnnotations在编译时生成子类,所以对性能没有影响
roboguice 帮你处理了很多代码异常,利用annotation使得更少的代码完成项目
butterknife 利用annotation帮你快速完成View的初始化,减少代码
Dagger 依赖注入,适用于Android和Java

AndroidAnnotations是一个能够让你快速进行Android开发的开源框架,它能让你专注于真正重要的地方。
使代码更加精简,使项目更加容易维护,它的目标就是“Fast Android Development.Easy maintainance”。
通过一段时间的使用发现,相比原生的Android开发,确实能够让你少些很多代码,它的首页也给出了一个简单
的例子,通过例子也可以看到代码比之前几乎少写了一半。
No Magic  [不知道为什么这样称呼,直译过来就是:无魔法,它的意思是:AndroidAnnotations在编译
的时候会产生一个子类(接下来你会明白),你查看这个子类,可以看到它是如何工作的]

 除了@Eactivity @ViewById@Click之外还有
@EApplication
@EBean
@EFragment
@EService
@EView
@EviewGroup
@App
@Bean
@Fullscreen
注意的一点就是:使用AndroidAnnotations千万要记得,编译的时候会生成一个子类,这个子类的名称就是在
原来的类之后加了一个下划线“_”,比如这个例子产生的子类名称为“MyActivity_”,这就需要你在注册这个Activity的时候,在
AndroidManifest.xml中将 MyActivity 改为 MyActivity_ ,使用的时候也是使用MyActivity_来表示此类,如从另一个Activity跳转
到此节目就要这样用:startActivity(new Intent(this,MyActivity_.class)); 
一、组件的注解
技术分享
@EActivity这个注解是用来修饰Activity的,向Activity注入布局,也可以设置页面的样式为全屏、无Title。这些使用具有实意的注解来实现,是不是很方便呀。对于其他的组件支持也是相当简单的,如@EService、@EReceiver、@EProvider、@EApplication、@EApplication、@EFragment。同时也能修饰自定义控件,注解为@EView、@EViewGroup。支持是不是相当全面
二、资源引用的注解
技术分享
如果你想获取系统服务,只要在你的变量前加上@SystemService注解。
获取Intent中传递的值,加上@Extra注解,同时容错性很好,如果接收不到这个key对应的value,也没问题,你可以设置默认值。再有就是强转失败也不会造成crash,比如传递的是个int值,接收的时候是个String,也没有问题,只是接收失败罢了。
三、事件绑定注解
技术分享
其他常用的还有@TextChange、@ItemClick、@SeekBarProgressChange。
四、异步线程与UI线程的交互
技术分享

当View相关的成员变量初始化完毕后,会调用拥有@AfterViews注解的方法,你可以在里面初始化一些界面控件等。如果其他的成员变量处事完毕,就会调用@AfterInject。

比如大多数应用的逻辑是这样的,初始化界面之后,就发起耗时的数据请求,然后解析获取到的数据,再设置到界面上。一般的涉及UI线程与异步任务交互的时候,相对都比较麻烦一些。让我们看下AA是如何实现的。

技术分享

很简单吧,UI线程执行的方法加个@UiThread,异步线程方法加个@Background,两者的交互就是方法直接的相互调用,其他的你不用关心,一切的实现都是AA的编译器去自动生成交互的代码。交互的过程,完全没有在执行异步的感觉,不用再使用Handler去发送接收Message了。两个注解就把以前一堆的代码实现的功能给实现了,真心给个最大的赞。

  五、Rest API

在AA中也支持Rest API,而且支持所有的HTTP请求方法。下面演示的是一个GET请求。

  1. @Rest("http://www.bookmarks.com")
  2. public interface BookmarkClient {
  3. @Get("/bookmarks/{userId}?search={search}")
  4. Bookmarks getBookmarks(String search, String userId);
  5. }
  1. @Background
  2. void searchAsync(String searchString, String userId) {
  3. Bookmarks bookmarks = restClient.getBookmarks(searchString, userId);
  4. updateBookmarks(bookmarks);
  5. }
定义一个请求的接口,然后就可以直接使用了,不需要自己再去实现。这个跟公司后台接口设计紧密相关,如果你公司接口交互都是Rest风格的话,你就重写下,好好体验AA的魅力吧

跟原始android界面处理业务逻辑:
 AndroidAnnotations工作在一个非常简单的方式。它会使用标准的Java注解处理工具自动添加一个额外的编译步骤生成的源代码。(译者注:即生成一个原有类名加“_”的类,这个类才是真正运行用的类)
 * 源代码是什么样子的?
例如每个使用@EActivity注解的activity,将生成这个activity的一个子类,它的名字是在activity名称末尾追加一个下划线。
例如,下面的类:
@EActivity
public class MyActivity extends Activity{
  // ...
}

将生成以下子类,在同一个包路径中,但在另一个源文件夹:(译者注:在测试过程中,并未在src目录下发现生成的类。但此类确实生成了,它在哪里呢?实际是在项目根目录的.apt_generated文件夹下,在eclipse中无法查看到,需要到资源管理其相应文件夹中查看。)
public final class MyActivity_ extends MyActivity{
  // ...
}

该子类重载一些方法(例如的onCreate()),通过【委托方式】调用了你的activity的相关方法。这就是为什么你必须在AndroidManifest.xml文件中为你的activity名称添加“_”的原因:
<activityandroid:name=".MyListActivity_"/>

 * 
 * 启动一个使用注解的activity
在原始的Android开发中,你通常是这样启动activity的:
startActivity(this,MyListActivity.class);

然而,如果使用AndroidAnnotations,真正被启动的activity是MyListActivity_:
startActivity(this,MyListActivity_.class);

创建Intent
1.AndroidAnnotations2.4及以上版本
我们提供了一个静态的助手方法,让你启动真正的activity:
// 启动 activity
MyListActivity_.intent(context).start();

// 创建一个intent使用 activity
Intentintent=MyListActivity_.intent(context).get();

// 你也可以设置flags
MyListActivity_.intent(context).flags(FLAG_ACTIVITY_CLEAR_TOP).start();

//你甚至可以在activity中使用@Extra定义扩展数据并作为activity的启动参数
MyListActivity_.intent(context).myDateExtra(someDate).start();

2.AndroidAnnotations2.7及以上版本
你还可以使用startActivityForResult()方法:
MyListActivity_.intent(context).startForResult();

启动一个使用注解的Service
在原始的Android开发中,你通常是这样启动一个服务的:
startService(this,MyService.class);
然而,如果使用AndroidAnnotations,则真正的服务MyService_将被启动:
startService(this,MyService_.class);

创建Intent
1.AndroidAnnotations2.7及以上版本
我们提供了一个静态的方法,让你启动生成的service:

// 启动service
MyService_.intent(context).start();

// 通过service创建一个intent
Intentintent=MyService_.intent(context).build();

// 你能在启动service时使用flags
MyService_.intent(context).flags(Intent.FLAG_GRANT_READ_URI_PERMISSION).start();
例如:
  1. /**
  2. *samy
  3. */
  4. @EActivity(R.layout.activity_a20thirdparty_androidannotations_aamain)
  5. // Sets content view to R.layout.translate
  6. public class AAMainAct extends Activity {
  7. @ViewById
  8. // Injects R.id.textInput
  9. // 提供id来生成控件,如果不指定ID,默认以控件名进行查找,如上面的myEditText
  10. EditText myEditText;
  11. @ViewById(R.id.myTextView)
  12. // Injects R.id.myTextView
  13. TextView textView;
  14. @AnimationRes
  15. // Injects android.R.anim.fade_in
  16. Animation fadeIn;
  17. @StringRes(R.string.hello)
  18. String helloFormat;
  19. @ColorRes
  20. int androidColor;
  21. @BooleanRes
  22. boolean someBoolean;
  23. @SystemService
  24. NotificationManager notificationManager;
  25. @SystemService
  26. WindowManager windowManager;
  27. //当View相关的成员变量初始化完毕后,会调用拥有@AfterViews注解的方法,你可以在里面初始化一些界面控件等。如果其他的成员变量处事完毕,就会调用@AfterInject。
  28. /**
  29. * AndroidAnnotations gracefully handles support for onBackPressed, whether you use ECLAIR (2.0), or pre ECLAIR android version.
  30. */
  31. public void onBackPressed() {
  32. super.onBackPressed();
  33. Toast.makeText(this, "Back key pressed!", Toast.LENGTH_SHORT).show();
  34. }
  35. @Override
  36. protected void onCreate(Bundle savedInstanceState) {
  37. super.onCreate(savedInstanceState);
  38. // windowManager should not be null
  39. windowManager.getDefaultDisplay();
  40. requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
  41. }
  42. // //事件控制,可以以按钮的id作为方法名,同时支持的事件还有onLongClick,onTextChange等
  43. // @LongClick
  44. // When R.id.myButtonClicked button is clicked
  45. // android:id="@+id/myButton"
  46. // 两种点击事件方法都可以的;myButton() myButtonClicked()
  47. @Click
  48. void myButton() {
  49. // void myButtonClicked() {
  50. String name = myEditText.getText().toString();
  51. setProgressBarIndeterminateVisibility(true);
  52. someBackgroundWork(name, 5);
  53. }
  54. /**
  55. * 对于@Click,方法名和xml文件中的id一样就可以这样写,AndroidAnnotations会自动识别,对于
  56. * 多个Button,可以写多个@Click,也可以在这样
  57. */
  58. // @Click({R.id.button1,R.id.button2,R.id.button3})
  59. // void buttonClicked(Button bt){
  60. // switch(bt.getId()){
  61. // case R.id.button1: //
  62. // break;
  63. // ...
  64. // }
  65. // }
  66. @Background
  67. // Executed in a background thread
  68. // 开启新线程后台运行,注意不要引用UI控件,而且返回值类型一定是void
  69. void someBackgroundWork(String name, long timeToDoSomeLongComputation) {
  70. try {
  71. TimeUnit.SECONDS.sleep(timeToDoSomeLongComputation);
  72. }
  73. catch (InterruptedException e) {
  74. }
  75. String message = String.format(helloFormat, name);
  76. updateUi(message, androidColor);
  77. showNotificationsDelayed();
  78. }
  79. @UiThread
  80. // Executed in the ui thread//UI线程
  81. void updateUi(String message, int color) {
  82. setProgressBarIndeterminateVisibility(false);
  83. textView.setText(message);
  84. textView.setTextColor(color);
  85. }
  86. @UiThread(delay = 2000)
  87. // 可以设置延时时间,以毫秒为单位
  88. void showNotificationsDelayed() {
  89. Notification notification = new Notification(R.drawable.ic_launcher, "Hello !", 0);
  90. PendingIntent contentIntent = PendingIntent.getActivity(this, 0, new Intent(), 0);
  91. notification.setLatestEventInfo(getApplicationContext(), "aa notification", "aa_test!", contentIntent);
  92. notificationManager.notify(1, notification);
  93. }
  94. // android:id="@+id/startExtraActivity"
  95. @LongClick
  96. void startExtraActivity() {
  97. // 这个传值有点不好弄
  98. Intent intent = AAWithExtraAct_.intent(this).myDate(new Date()).myMessage("hello !").classCastExceptionExtra("42").get();
  99. // Intent intent = ActivityWithExtra_.intent(this).myDate(new Date()).myMessage("hello !").get();
  100. // intent.putExtra(ActivityWithExtra_.MY_INT_EXTRA, 42);
  101. startActivity(intent);
  102. }
  103. @Click
  104. void startListActivity(View v) {
  105. startActivity(new Intent(this, AAListAct_.class));
  106. }
  107. @Touch
  108. void myTextView(MotionEvent event) {
  109. Toast.makeText(this, "myTextView was touched!: " , Toast.LENGTH_SHORT).show();
  110. }
  111. @Transactional
  112. int transactionalMethod(SQLiteDatabase db, int someParam) {
  113. return 42;
  114. }
  115. }


说到这里不得推荐一款开源框架:Butter Knife 

Butter Knife也是使用注入视图的方式使开发人员尽可能少的编写代码。相比AndroidAnnotations,个人觉得没有AndroidAnnotations

使用简单,而且文档几乎也没有。还是先看一小段代码吧:

  1. package com.example.butterknife;
  2. import android.app.Activity;
  3. import android.os.Bundle;
  4. import android.widget.Button;
  5. import android.widget.ListView;
  6. import android.widget.TextView;
  7. import android.widget.Toast;
  8. import butterknife.InjectView;
  9. import butterknife.OnClick;
  10. import butterknife.ButterKnife;
  11. import butterknife.OnItemClick;
  12. import butterknife.OnLongClick;
  13. import static android.widget.Toast.LENGTH_SHORT;
  14. public class SimpleActivity extends Activity {
  15. @InjectView(R.id.title) TextView title;
  16. @InjectView(R.id.subtitle) TextView subtitle;
  17. @InjectView(R.id.hello) Button hello;
  18. @InjectView(R.id.list_of_things) ListView listOfThings;
  19. @InjectView(R.id.footer) TextView footer;
  20. private SimpleAdapter adapter;
  21. @OnClick(R.id.hello) void sayHello() {
  22. Toast.makeText(this, "Hello, views!", LENGTH_SHORT).show();
  23. }
  24. @OnLongClick(R.id.hello) boolean sayGetOffMe() {
  25. Toast.makeText(this, "Let go of me!", LENGTH_SHORT).show();
  26. return true;
  27. }
  28. @Override protected void onCreate(Bundle savedInstanceState) {
  29. super.onCreate(savedInstanceState);
  30. setContentView(R.layout.simple_activity);
  31. ButterKnife.inject(this);
  32. // Contrived code to use the "injected" views.
  33. title.setText("Butter Knife");
  34. subtitle.setText("View \"injection\" for Android.");
  35. footer.setText("by Jake Wharton");
  36. hello.setText("Say Hello");
  37. }
  38. }

总之,两者虽有相似的地方,但看到AndroidAnnotations之后,就不愿使用Butter Knife了。另外,值得你注意的是butter Knife

有个代码生成的插件呢,不过是针对Android Studio的,请看图:


技术分享

(gif 的图为什么不会动啊)

  • 插件使用:
  • 在所使用的布局 ID 上点击右键 (例如上图中的 R.layout.activity_settings ), 
  • 然后选择 Generate -> Generate ButterKnife Injections
  • 在对话框中选择需要注入的 View, 还有个选项可以给 Adapter 创建一个 ViewHolder。
  • 点击 Confirm , 代码自动生成!

    插件项目主页:
    https://github.com/inmite/android-butterknife-zelezny
    下载插件:
    http://plugins.jetbrains.com/plugin/7369

  • 代码如下:
    1. public class MainActivity extends ActionBarActivity {
    2. @Override
    3. protected void onCreate(Bundle savedInstanceState) {
    4. super.onCreate(savedInstanceState);
    5. // Try to generate Activity injections by clicking to R.layout.activity_main
    6. setContentView(R.layout.activity_main);
    7. if (savedInstanceState == null) {
    8. getSupportFragmentManager().beginTransaction()
    9. .add(R.id.container, new Fragment())
    10. .commit();
    11. }
    12. }
    13. }
    2015年4月 星期六 19:30:36 edit by samy

    AndroidAnnotations用法总结

    标签:

    原文地址:http://www.cnblogs.com/hongfeiliuxing/p/4468307.html

    (0)
    (0)
       
    举报
    评论 一句话评论(0
    登录后才能评论!
    © 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
    迷上了代码!