說明
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[]?.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=
@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
拷貝到項目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的洩露,進而導緻記憶體洩露。