一探究竟:安卓老牌註解框架androidannotations
簡介
AndroidAnnotations is an Open Source framework that speeds up Android development. It takes care of the plumbing, and lets you concentrate on what’s really important. By simplifying your code, it facilitates its maintenance.
Fast Android Development. Easy maintainance翻譯一下:
AndroidAnnotations是一個能讓你進行快速開發的開源框架,它讓你關注真正重要的地方,它可以簡化你的程式碼,並且有利於你後期的維護;
快速開發,簡單可維護
這就是AndroidAnnotations, 一款讓你用了就停不下來的快速開發易維護的開源框架,ok,下面就跟著我的腳步,一起來揭開它的神祕面紗…
直接上程式碼:
package com.rest.template.resttemplate.activities;
import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.widget.Button;
import com.rest.template.resttemplate.R;
import com.rest.template.resttemplate.client.RestClient;
import com.rest.template.resttemplate.client.facades.IpFacade;
import com.rest.template.resttemplate.client.facades.ResponseHeadersFacade;
import com.rest.template.resttemplate.client.listener.RestClientListener;
import com.rest.template.resttemplate.client.model.template.Ip;
import com.rest.template.resttemplate.client.model.template.ResponseTest;
import org.androidannotations.annotations.AfterViews;
import org.androidannotations.annotations.Bean;
import org.androidannotations.annotations.Click;
import org.androidannotations.annotations.EActivity;
import org.androidannotations.annotations.UiThread;
import org.androidannotations.annotations.ViewById;
/**
* 這裡加註解就可以不寫onCreate()方法
* 直接繫結xml佈局檔案
*/
@EActivity(R.layout.activity_main)
public class MainActivity extends AppCompatActivity {
private static final String TAG = "SplashScreenActivity";
@Bean
protected RestClient restClient;
@Bean
protected IpFacade ipFacade;
@Bean
protected ResponseHeadersFacade responseHeadersFacade;
/**
* 正常控制元件的註解模式,類似findviewbyid
*/
@ViewById(R.id.id_button)
Button id_button;
/**
* 變數名與控制元件ID相同時,省略@ViewById後邊的id
*/
@ViewById
Button response_test_button;
/**
* 多個控制元件的點選事件
* 如果控制元件ID與變數名一致,在@ViewById後沒有寫控制元件ID, 則在使用時就不能直接在方法中呼叫,
* 因為在執行時會報一個空指標,所以需要在AfterView註解的方法中進行使用
* @param button
*/
@Click({R.id.id_button,R.id.response_test_button})
public void clicks(Button button){
switch (button.getId()){
case R.id.id_button:
break;
case R.id.response_test_button:
break;
default:
}
}
@AfterViews
protected void initGui() {
restClient.cancelAll();
}
/**
* 正常點選事件的註解方式
*/
@Click(R.id.id_button)
public void onIpClick() {
ipFacade.getIp(new RestClientListener<Ip>() {
@Override
public void onSuccess(Ip ip) {
onSuccessResult(ip);
}
@Override
public void onFailed(Exception ex, String msg) {
onFailedResult(ex, msg);
}
});
}
/**
* 點選事件註解,控制元件ID與方法名一致,
* 省略onClick()括號內控制元件ID
*/
@Click
public void response_test_button(){
showDialog("控制元件ID與方法名一致,省略ID");
}
// @Click(R.id.response_test_button)
// public void onResponseTestClick() {
// responseHeadersFacade.getResponseHeaders("TEST", "TEST_VALUE", new RestClientListener<ResponseTest>() {
// @Override
// public void onSuccess(ResponseTest responseTest) {
// onSuccessResult(responseTest);
// }
//
// @Override
// public void onFailed(Exception ex, String msg) {
// onFailedResult(ex, msg);
// }
// });
// }
private void onSuccessResult(Object object) {
Log.e(TAG, object.toString());
showDialog(object.toString());
}
private void onFailedResult(Exception ex, String msg) {
if(ex != null) {
Log.e(TAG, msg, ex);
} else {
Log.e(TAG, msg);
}
}
@UiThread
protected void showDialog(final String message) {
new AlertDialog.Builder(MainActivity.this)
.setTitle(getString(R.string.information))
.setMessage(message)
.show();
}
}
PS:其他常用註解欄位:
>
@StringRes : 表示引數、變數或者函式返回值應該是一個字串型別的資源
@ColorInt : 表示引數、變數或者函式返回值應該是一個顏色值而不是顏色資源引用,例如應該是一個 AARRGGBB 的整數值。
@ColorRes : 表示引數、變數或者函式返回值應該是一個 color 型別的資源,而不是顏色值。注意和 ColorInt 區別
@AnimRes : 表示引數、變數或者函式返回值應該是一個 Anim 型別的資源
@DrawableRes : 表示引數、變數或者函式返回值應該是一個 drawable 型別的資源
@DimenRes : 表示引數、變數或者函式返回值應該是一個 dimension 型別的資源
@AfterInject 定義的方法在類的構造方法執行後執行
@AfterTextChange定義的方法在TextView及其子類的Text屬性改變後執行
@AfterViews 定義的方法在setContentView後執行
@Background //開啟新執行緒後臺執行,注意不要引用UI控制元件,而且返回值型別一定是void
@UiThread 定義的方法在主執行緒執行
@UiThread(delay=2000) //可以設定延時時間,以毫秒為單位
@BeforeTextChange 定義的方法在TextView及其子類的Text屬性改變前執行
@Click //事件控制,可以以按鈕的id作為方法名,同時支援的事件還有onLongClick,onTextChange等
@EActivity //佈局檔案在這裡宣告,不用在setContentView
@EProvider 在 ContentProvider中啟用Annotations
@EReceive 在BroadcastReceiver中啟用Annotations
@EService 在Service中啟用Annotations
@EView 在自定義的View的子類中啟用Annotations
@Fullscreen 全屏
@NoTitle 無標題欄
@ViewById //控制元件這樣標註,由於是IOC模式,因此不需要自己例項化
@ViewById(R.id.myTextView) //提供id來生成控制元件,如果不指定ID,預設以控制元件名進行查詢,如上面的myEditText
@StringRes(R.string.hello) //String資源
@DimensionRes(R.dimen.activity_horizontal_margin)//dimen資源
@Extra(MainActivity.NAME_KEY) //取Intent傳遞的值
@WindowFeature({Window.FEATURE_NO_TITLE,Window.FEATURE_INDETERMINATE_PROGRESS})
執行緒註解
執行緒註解主要是用於檢測一個函式是否在指定型別的執行緒中執行,有四種註解型別;
@UiThread
@MainThread
@WorkerThread
@BinderThread
其中@UiThread 和 @MainThread 在大部分的使用場景中,是可以替換使用的,如果一個類中的所有方法都在同一個執行緒中執行,就直接可以在類本身進行註解;
對於程式碼示例,已AsyncTask最為合適不過,我們都知道doInBackground方法為WorkThread,不可以進行UI更新,所以如果在onProgressUpdate方法外進行UI更新的話,IDE就會給我們直接的提示
值約束註解 @FloatRange,@IntRange, @Size
@FloatRange 用法
如果在定義的方法中,需要傳的引數是一個Float或者Double型別,而且又需要保證值在一定範圍內,就可以使用 @FloatRange 註解,如圖所示,如果設定範圍為0.0~1.0,如果傳值為12,IDE就會直接給出提示
@IntRange用法
當然,你也可以對int值進行約束限定,比如限定為0~255,如果傳值300,就會報出錯誤提示
@Size用法
對於資料,集合及字串我們可以用@Size進行限制,用法如下:
字串最常為10: @Size(max=10)
![這裡寫圖片描述](https://img-blog.csdn.net/20180416140301165?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3l0ZnVubnlzaXRl/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70)
陣列只能有2個元素: @Size(2)
![這裡寫圖片描述](https://img-blog.csdn.net/20180416140330485?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3l0ZnVubnlzaXRl/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70)
集合不能為空,至少有一個元素: @Size(min=1)
### 許可權註解: @RequiresPermission
如果我們的方法需要某些許可權,但是又不知道在清單檔案中是否配置了,我們就可以使用這個許可權註解;
@RequiresPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE)
public void writeInfo(String name){
//TODO what you want
}
如果需要多個許可權的一個,使用 anyOf 屬性:
@RequiresPermission(anyOf={Manifest.permission.WRITE_EXTERNAL_STORAGE,Manifest.permission.READ_EXTERNAL_STORAGE}) <br>
public void writeInfo(String name){ <br>
//TODO what you want <br>
}
如果需要使用多個許可權,使用 allOf 屬性:
@RequiresPermission(allOf = {Manifest.permission.WRITE_EXTERNAL_STORAGE,Manifest.permission.READ_EXTERNAL_STORAGE}) <br>
public void writeInfo(String name){ <br>
//TODO what you want <br>
}
intent許可權註解
@RequiresPermission(Manifest.permission.BLUETOOTH)
public static final String ACTION_VIEW = "android.bluetooth.adapter.action.REQUEST_DISCOVERABLE";
Content Provider 許可權註解
相信我們每個打包的小夥伴都知道,如果想keep某個類裡面的某個方法是一件多麼痛苦的事情,你曾經在Proguard用到過類似這樣的程式碼:
-keep class com.foo.bar { public static }
使用註解就會很方便的接軍這些問題,AndroidAnnotations將會告訴Proguard不要對指定的函式或者類進行優化操作:
@Keep
public void setAnni(@IntRange(from=0, to=255) int anni){
//TODO what you want
}
@RequiresPermissions 解釋
@RequiresAuthentication
驗證使用者是否登入,等同於方法subject.isAuthenticated() 結果為true時。
@RequiresUser
驗證使用者是否被記憶,user有兩種含義:
一種是成功登入的(subject.isAuthenticated() 結果為true);
另外一種是被記憶的(subject.isRemembered()結果為true)。
@RequiresGuest
驗證是否是一個guest的請求,與@RequiresUser完全相反。
換言之,RequiresUser == !RequiresGuest。
此時subject.getPrincipal() 結果為null.
@RequiresRoles
例如:@RequiresRoles("aRoleName");
void someMethod();
如果subject中有aRoleName角色才可以訪問方法someMethod。如果沒有這個許可權則會丟擲異常AuthorizationException。
@RequiresPermissions
例如: @RequiresPermissions({"file:read", "write:aFile.txt"} )
void someMethod();
要求subject中必須同時含有file:read和write:aFile.txt的許可權才能執行方法someMethod()。否則丟擲異常AuthorizationException。