说明
AndroidAnnotations(以下简称AA)是一个能让你专注于更快速的开发Android 应用的开源框架,当你的项目中引入对他的使用能够让你的代码看起来更加的简洁,更加有利于代码的可阅读性,使你的项目更加容易维护。
这里奉上项目地址 AndroidAnnotations Github。
特性
- 依赖注入:inject views, extras, system services, resources, …
- 简化线程模型:通过注释的方式指定当前的方法要执行在什么线程,抛弃繁琐的AsyncTask,Thread等书写方式
- 事件绑定:通过使用注释的方式来处理点击事件@Click,文本内容改变监听@TextChange,@OnLongClick长按事件、等等…抛弃了传统的setonclicklistener等的复杂写法
- REST客户端:创建一个网络连接客户端接口
- No magic:官方文档中给出了这样一个词语来描述这其中的一个特性"没有魔法",起初阅读时我并不能理解他想说的,当我详细查看他实现的原理的时候,我想我或许明白他所说的No magic是什么意思了,即他与别的框架不同的是,AA是在编译时生成当前注释类的直接final子类代码,而非运行时利用反射的方式处理事件。java的反射是神奇的,Magic的,它可以让你将对方隐藏起来的方法属性拿到手(当然你拿到手做什么就是你的需求了),但随之而来的是性能的降低,相比于利用反射,AA的编译时生成代码就是No Magic的。
配置
Eclipse
在Eclipse中使用AA你可能需要下载以下俩个Jar文件 [ androidannotations-api ],[ androidannotations ]
- 首先将androidannotations-api.jar放入libs目录中
- 在Eclipse项目中新建一个与libs目录平级的compile-libs文件夹,将androidannotations.jar包拷贝到该文件夹中
- 右击项目选中Properties选项
- 在Java Compiler选项下的Annotations Processin项中的第一项勾上
- 将Factory Path项的第一项勾上,并且点击Add JARs按钮
- 找到该项目之前创建的compile-libs文件中添加的jar包,OK
- Eclipse下配置完成
AndroidStudio
项目Build.gradle中添加如下依赖
dependencies {
compile fileTree(include: ['*.jar', '*.arr'], dir: 'libs')
compile 'org.androidannotations:androidannotations:4.1.0'
}
**当然你也可以选择官方的添加方式
apply plugin: 'com.android.application'
//step 1
//添加依赖插件,定义版本号
apply plugin: 'android-apt'
def AAVersion = '4.1.0'
//step 2
buildscript {
//指定远程仓库
repositories {
mavenCentral()
}
//依赖库
dependencies {
// 记得保持版本号与您根目录下 build.gradle 中所依赖的版本号一致
classpath 'com.android.tools.build:gradle:2.2.+'
// 保持最新的版本号,当前是1.8
// 最新版查看地址-http://mvnrepository.com/artifact/com.neenbedankt.gradle.plugins/android-apt
classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8'
}
}
//step 3
apt {
arguments {
androidManifestFile variant.outputs[0]?.processResources?.manifestFile
}
}
// step 4
dependencies {
// ......
// 具体的依赖
apt "org.androidannotations:androidannotations:$AAVersion"
compile "org.androidannotations:androidannotations-api:$AAVersion"
}
android {
//.......
}
###Talk is cheap. Show me the code.
@EActivity(R.layout.activity_main)
@Fullscreen //全屏
@WindowFeature(Window.FEATURE_NO_TITLE)
//Fragment:@EFragment
//类:@EBean
public class MainActivity extends Activity {
@App
BaseApplication app;
//代替findViewById(当你的名称相同的时候可以不用写(R.id.button) )
@ViewById
TextView tvAmText;
@ViewById(R.id.button)
Button mButton;
@ViewsById({R.id.tv_asa_model,R.id.tv_asa_sn})//一次引入多个
TextView tvAsaModel,tvAsaSn;
//引入 String 资源,id 的使用同上
@StringRes
String spinner_dept_tips;
//以下资源的引用同上
/**
* @AnimationRes
* @BooleanRes
* @ColorRes
* @ColorStateListRes
* @DimensionRes
* @DrawableRes
* @HtmlRes
* @IntArrayRes
* @IntegerRes
* @LayoutRes
* @MovieRes
* @StringArrayRes
* @StringRes
* @TextArrayRes
* @TextRes
*/
/**
* Intent intent=getIntent();
* String asset_id = intent.getStringExtra("asset_id");
*/
@Extra("asset_id"
String asset_id;
//取代原来的clipboardManager = (ClipboardManager) getSystemService(CLIPBOARD_SERVICE);
@SystemService
ClipboardManager mCBManager;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//MainActivity 的 onCreate() 方法中不要执行任何与 layout 控件相关的操作
}
/**
* 初始化控件
* 在初始化控件的时候一定要注意加上@AfterViews注解
否则可能会报空指针异常
*/
@AfterViews
void initView() {
tvAmText.setText("开始学习注解的使用");
}
//点击事件,同理,长按:@LongClick,触摸:@Touch
/**
* @LongClick 长按触摸
* @Touch 触摸
* @ItemClick 条目点击事件
*/
@Click(R.id.button)
void btClick() {
Toast.makeText(MainActivity.this, "start", Toast.LENGTH_SHORT).show();
doInBack();
}
/**
*
*/
@Background
void doInBack() {
//当前方法执行线程为子线程
}
@UiThread
/**
* 在子线程中更新 UI 线程
*/
void doInUiThread() {
//当前方法执行在主线程
}
private final static int REQUEST_CODE=0x1001
@OnActivityResult(REQUEST_CODE)
void onResult(int resultCode) {
}
}
###优点:
- 提高了开发的效率
- 代码看起来更加整洁
- 方便统一管理
- 提高了代码的复用性
- 代码的可阅读性大大提高
- 编译时注解,避免使用反射带来的性能影响
- 更快速的线程切换
###缺点:
-
出错抛异常的时候难以看懂(因为他会抛出很多无关的错误信息),难以定位。
- 问题排查
- 首先检测你使用了EActivity的Activity在注册时是否使用了下划线结尾
- 查看异常信息的最后几行,往往是问题的关键,前边抛出的问题基本上都是由于最后几行的异常产生的衍生问题,当你解决了最后边的异常信息重新编译基本就OK了
- 这里记录一个问题’com.android.support.test.espresso:espresso-core:2.2.2’的使用会导致出现同包名类的重复被引用(javax.annotation.CheckForNull),导致无法编译打包。解决方案:删掉espresso的依赖
- 问题排查
-
会额外生成一些方法,方法数很容易爆表(eg:java.lang.IllegalArgumentException: method ID not in [0, 0xffff]: 65536 或者java.util.concurrent.ExecutionException: com.android.dex.DexIndexOverflowException: method ID not in [0, 0xffff]: 65536)当然随着Android 5.0和multidex的出现,现在这个问题也不是问题了
- multidex-1.0.1.aar去哪儿下载?
> 其实他就在你的SDK里边
> android-sdk-linux/extras/android/m2repository/com/android/support/multidex/1.0.1/multidex-1.0.1.aar
- multidex-1.0.1.aar去哪儿下载?
拷贝到项目libs目录下添加依赖
dependencies {
compile fileTree(include: ['*.jar', '*.arr'], dir: 'libs')
compile 'com.android.support:multidex:1.0.1'
}
###Tips
- 成员变量或方法不要声明为私有,否则会在编译时出错(因为AA是在编译时产生一个他的直接子类,解析注释生成代码,而子类无法继承父类的私有变量)
- 当你的Activity使用了@EActivity注解的时候 在 Mainfest 中注册MainActivity_ 而不是 MainActivity。
- Drawable、Adapter、View或其他和Context相关的对象,都不可以被标注。如果标注了,将会引起这些资源或view的泄露,从而导致内存泄露。