Android Annotations 注解例子


  1、AndroidAnnotations官網: http://androidannotations.org/ (也許你需要翻牆)

  2、eclipse中使用androidannotations的配置方法說明:https://github.com/excilys/androidannotations/wiki/Eclipse-Project-Configuration

  3、Android Studio中配置AndroidAnnotations:(這個是我這篇博文中要涉及到的!)

一、Android Studio配置androidannotations環境。

1、首先你建立一個module之后,在對應的app中會有一個名為build.gradle的文件(該module有效),而在整個項目外面也會有一個名為build.gradle的文件(全局有效)【這個工具中的application的目錄下(相當於Eclipse下的workspace)是可以有多個module的(相當於Eclipse下的project)】

2、我們配置的時候大概要分為下面兩步

在局部build.gradle中(加入 紅色字體部分 ):

 

apply plugin: 'com.android.application'

 

apply plugin: 'android-apt'

 

android {

    compileSdkVersion 19

    buildToolsVersion "20.0.0"

    defaultConfig {

        applicationId "com.tongbu.mytest"

        minSdkVersion 8

        targetSdkVersion 19

        versionCode 1

        versionName "1.0"

    }

    buildTypes {

        release {

            runProguard false

            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'

        }

    }

}

dependencies {

    compile fileTree(dir: 'libs', include: ['*.jar'])

    compile 'com.android.support:appcompat-v7:19.+'

   

apt "org.androidannotations:androidannotations:$AAVersion"

 

}

 

apt {

    arguments {

        androidManifestFile variant.processResources.manifestFile

        resourcePackageName 'com.tongbu.mytest'

    }

}

 

 

在全局build.gradle中(加入 紅色字體部分 ):

 

 

buildscript {

    repositories {

        jcenter()

    }

    dependencies {

        classpath 'com.android.tools.build:gradle:0.12.+'

        classpath 'com.neenbedankt.gradle.plugins:android-apt:1.3'

    }

}

allprojects {

    repositories {

        jcenter()

    }

}

 

如果以上的都順利完成了,那么恭喜你已經快配置完了,還需要把AndroidManifest.xml中的Activity的名字后面加上 _(下划線),因為這個框架解析編譯的時候,比如類MainActivity會被解析成MainActivity_.class,所以在清單文件中我們要在Activity的名字后面加一個下划線,或者androidannotation會報錯!

但並不會這么順利,在你補充完下划線之后,你會發現會提示你找不到MainActivity_這個東東

那么怎么辦呢??我們說了它是在編譯的時候整出來的,那我們只要按一下編譯的按鈕即可生成了!!

這樣子androidannotation在android studio上的環境就配置好了

Android 最火快速開發框架AndroidAnnotations簡介文章中的簡單介紹,本篇注重講解AndroidAnnotations中注解方法的使用。

@EActivity

 

 示例:

@EActivity(R.layout.main) public class MyActivity extends Activity { }

@fragment

示例:

 

@EFragment(R.layout.my_fragment_layout) public class MyFragment extends Fragment { }

注冊:

 

 

<fragment
        android:id="@+id/myFragment" android:name="com.company.MyFragment_" android:layout_width="fill_parent" android:layout_height="fill_parent" />

 

創建:

 

MyFragment fragment = new MyFragment_();

 

 

普通類:

 

@EBean
public class MyClass { }

 

 

注意:這個類必須僅僅只能有一個構造函數,參數最多有一個context。

Activity中使用:

 

@EActivity
public class MyActivity extends Activity { @Bean MyOtherClass myOtherClass; }

 

 

也可以用來聲明接口:

 

@Bean(MyImplementation.class) MyInterface myInterface;

 

 

在普通類中還可以注入根環境:

 

@EBean
public class MyClass { @RootContext Context context; // Only injected if the root context is an activity @RootContext Activity activity; // Only injected if the root context is a service @RootContext Service service; // Only injected if the root context is an instance of MyActivity @RootContext MyActivity myActivity; }

 

 

如果想在類創建時期做一些操作可以:

 

@AfterInject
  public void doSomethingAfterInjection() { // notificationManager and dependency are set }

 

 

單例類需要如下聲明:

 

@EBean(scope = Scope.Singleton) public class MySingleton { }

 

 

注意:在單例類里面不可以注入view和事件綁定,因為單例的生命周期比Activity和Service的要長,以免發生內存溢出。

@EView

 

@EView
public class CustomButton extends Button { @App MyApplication application; @StringRes String someStringResource; public CustomButton(Context context, AttributeSet attrs) { super(context, attrs); } }

 

 

注冊:

 

<com.androidannotations.view.CustomButton_
        android:layout_width="match_parent" android:layout_height="wrap_content" />

 

 

創建:

 

CustomButton button = CustomButton_.build(context);

 

 

@EViewGroup

 

@EViewGroup(R.layout.title_with_subtitle) public class TitleWithSubtitle extends RelativeLayout { @ViewById protected TextView title, subtitle; public TitleWithSubtitle(Context context, AttributeSet attrs) { super(context, attrs); } public void setTexts(String titleText, String subTitleText) { title.setText(titleText); subtitle.setText(subTitleText); } }

 

 

注冊:

 

<com.androidannotations.viewgroup.TitleWithSubtitle_
        android:id="@+id/firstTitle" android:layout_width="match_parent" android:layout_height="wrap_content" />

 

 

@EApplication

 

@EApplication
public class MyApplication extends Application { }
Activity中使用:
@EActivity
public class MyActivity extends Activity { @App MyApplication application; }
@EService
@EService
public class MyService extends Service { }
跳轉service:
MyService_.intent(getApplication()).start();
停止service:
MyService_.intent(getApplication()).stop();
@EReceiver
@EReceiver
public class MyReceiver extends BroadcastReceiver { }
@Receiver
可以替代聲明BroadcastReceiver
@EActivity
public class MyActivity extends Activity { @Receiver(actions = "org.androidannotations.ACTION_1") protected void onAction1() { } }
 
@EProvider
@EProvider
public class MyContentProvider extends ContentProvider { }
@ViewById
@EActivity
public class MyActivity extends Activity { // Injects R.id.myEditText,變量名稱必須和布局的id名稱一致 @ViewById EditText myEditText; @ViewById(R.id.myTextView) TextView textView;

@ViewByIds({R.id.id1,R.id.id2})
List<TextView> list; }




@AfterViews
@EActivity(R.layout.main) public class MyActivity extends Activity { @ViewById TextView myTextView; @AfterViews void updateTextWithDate() {
//一定要在這里進行view的一些設置,不要在oncreate()中設置,因為oncreate()在執行時 view還沒有注入
myTextView.setText("Date: " + new Date()); }[...]
@StringRes
@EActivity
public class MyActivity extends Activity { @StringRes(R.string.hello) String myHelloString;//不能設置成私有變量 @StringRes String hello; }
@ColorRes
@EActivity
public class MyActivity extends Activity { @ColorRes(R.color.backgroundColor) int someColor; @ColorRes int backgroundColor; }
 
@AnimationRes
@EActivity
public class MyActivity extends Activity { @AnimationRes(R.anim.fadein) XmlResourceParser xmlResAnim; @AnimationRes Animation fadein; }
 
@DimensionRes
@EActivity
public class MyActivity extends Activity { @DimensionRes(R.dimen.fontsize) float fontSizeDimension; @DimensionRes float fontsize; }
 
@DImensionPixelOffsetRes
@EActivity
public class MyActivity extends Activity { @DimensionPixelOffsetRes(R.string.fontsize) int fontSizeDimension; @DimensionPixelOffsetRes int fontsize; }
 
@DimensionPixelSizeRes
@EActivity
public class MyActivity extends Activity { @DimensionPixelSizeRes(R.string.fontsize) int fontSizeDimension; @DimensionPixelSizeRes int fontsize; }
其他的Res:
  • @BooleanRes
  • @ColorStateListRes
  • @DrawableRes
  • @IntArrayRes
  • @IntegerRes
  • @LayoutRes
  • @MovieRes
  • @TextRes
  • @TextArrayRes
  • @StringArrayRes
 
@Extra
@EActivity
public class MyActivity extends Activity { @Extra("myStringExtra") String myMessage; @Extra("myDateExtra") Date myDateExtraWithDefaultValue = new Date(); }
或者:
@EActivity
public class MyActivity extends Activity { // The name of the extra will be "myMessage",名字必須一致 @Extra String myMessage; }
傳值:
MyActivity_.intent().myMessage("hello").start() ;
 
@SystemService
@EActivity
public class MyActivity extends Activity {// @SystemService NotificationManager notificationManager; }
 
@HtmlRes
@EActivity
public class MyActivity extends Activity { // Injects R.string.hello_html @HtmlRes(R.string.hello_html) Spanned myHelloString; // Also injects R.string.hello_html @HtmlRes CharSequence helloHtml; }
 
@FromHtml
@EActivity
public class MyActivity extends Activity {//必須用在TextView @ViewById(R.id.my_text_view) @FromHtml(R.string.hello_html) TextView textView; // Injects R.string.hello_html into the R.id.hello_html view @ViewById @FromHtml TextView helloHtml; }
 
@NonConfigurationInstance
public class MyActivity extends Activity {//等同於 Activity.onRetainNonConfigurationInstance() @NonConfigurationInstance Bitmap someBitmap; @NonConfigurationInstance @Bean MyBackgroundTask myBackgroundTask; }
 
@HttpsClient
@HttpsClient
HttpClient httpsClient;
示例:
@EActivity
public class MyActivity extends Activity { @HttpsClient(trustStore=R.raw.cacerts, trustStorePwd="changeit", hostnameVerif=true) HttpClient httpsClient; @AfterInject @Background public void securedRequest() { try { HttpGet httpget = new HttpGet("https://www.verisign.com/"); HttpResponse response = httpsClient.execute(httpget); doSomethingWithResponse(response); } catch (Exception e) { e.printStackTrace(); } } @UiThread public void doSomethingWithResponse(HttpResponse resp) { Toast.makeText(this, "HTTP status " + resp.getStatusLine().getStatusCode(), Toast.LENGTH_LONG).show(); } }
 
@FragmentArg
@EFragment
public class MyFragment extends Fragment {//等同於 Fragment Argument @FragmentArg("myStringArgument") String myMessage; @FragmentArg String anotherStringArgument; @FragmentArg("myDateExtra") Date myDateArgumentWithDefaultValue = new Date(); }
MyFragment myFragment = MyFragment_.builder() .myMessage("Hello") .anotherStringArgument("World") .build();
 
@Click
@Click(R.id.myButton) void myButtonWasClicked() { [...] } @Click void anotherButton() {//如果不指定則函數名和id對應 [...] } @Click void yetAnotherButton(View clickedView) { [...] }
其他點擊事件:
  • Clicks with @Click
  • Long clicks with @LongClick
  • Touches with @Touch

AdapterViewEvents 

  • Item clicks with @ItemClick
  • Long item clicks with @ItemLongClick
  • Item selection with @ItemSelect
有兩種方式調用:
1.
@EActivity(R.layout.my_list) public class MyListActivity extends Activity { // ... @ItemClick public void myListItemClicked(MyItem clickedItem) {//MyItem是adapter的實體類,等同於adapter.getItem(position) } @ItemLongClick public void myListItemLongClicked(MyItem clickedItem) { } @ItemSelect public void myListItemSelected(boolean selected, MyItem selectedItem) { } }
2.
@EActivity(R.layout.my_list) public class MyListActivity extends Activity { // ... @ItemClick public void myListItemClicked(int position) {//位置id } @ItemLongClick public void myListItemLongClicked(int position) { } @ItemSelect public void myListItemSelected(boolean selected, int position) { } }
 
@SeekBarProgressChange
//等同於SeekBar.OnSeekBarChangeListener.onProgressChanged(SeekBar, int, boolean)
@SeekBarProgressChange(R.id.seekBar) void onProgressChangeOnSeekBar(SeekBar seekBar, int progress, boolean fromUser) { // Something Here } @SeekBarProgressChange(R.id.seekBar) void onProgressChangeOnSeekBar(SeekBar seekBar, int progress) { // Something Here } @SeekBarProgressChange({R.id.seekBar1, R.id.seekBar2}) void onProgressChangeOnSeekBar(SeekBar seekBar) { // Something Here } @SeekBarProgressChange({R.id.seekBar1, R.id.seekBar2}) void onProgressChangeOnSeekBar() { // Something Here }@SeekBarTouchStart and @SeekBarTouchStop
 
@SeekBarTouchStart 和 @SeekBarTouchStop
接受開始和結束事件的監聽
 
@TextChange
@TextChange(R.id.helloTextView) void onTextChangesOnHelloTextView(CharSequence text, TextView hello, int before, int start, int count) { // Something Here } @TextChange void helloTextViewTextChanged(TextView hello) { // Something Here } @TextChange({R.id.editText, R.id.helloTextView}) void onTextChangesOnSomeTextViews(TextView tv, CharSequence text) { // Something Here } @TextChange(R.id.helloTextView) void onTextChangesOnHelloTextView() { // Something Here }
 
@BeforeTextChange
@BeforeTextChange(R.id.helloTextView) void beforeTextChangedOnHelloTextView(TextView hello, CharSequence text, int start, int count, int after) { // Something Here } @BeforeTextChange void helloTextViewBeforeTextChanged(TextView hello) { // Something Here } @BeforeTextChange({R.id.editText, R.id.helloTextView}) void beforeTextChangedOnSomeTextViews(TextView tv, CharSequence text) { // Something Here } @BeforeTextChange(R.id.helloTextView) void beforeTextChangedOnHelloTextView() { // Something Here }
 
@AfterTextChange
@AfterTextChange(R.id.helloTextView) void afterTextChangedOnHelloTextView(Editable text, TextView hello) { // Something Here } @AfterTextChange void helloTextViewAfterTextChanged(TextView hello) { // Something Here } @AfterTextChange({R.id.editText, R.id.helloTextView}) void afterTextChangedOnSomeTextViews(TextView tv, Editable text) { // Something Here } @AfterTextChange(R.id.helloTextView) void afterTextChangedOnHelloTextView() { // Something Here }
@OptionsMenu和OptionsItem
@EActivity
@OptionsMenu(R.menu.my_menu) public class MyActivity extends Activity { @OptionMenuItem MenuItem menuSearch; @OptionsItem(R.id.menuShare) void myMethod() { // You can specify the ID in the annotation, or use the naming convention } @OptionsItem void homeSelected() { // home was selected in the action bar // The "Selected" keyword is optional } @OptionsItem boolean menuSearch() { menuSearch.setVisible(false); // menuSearch was selected // the return type may be void or boolean (false to allow normal menu processing to proceed, true to consume it here) return true; } @OptionsItem({ R.id.menu_search, R.id.menu_delete }) void multipleMenuItems() { // You can specify multiple menu item IDs in @OptionsItem } @OptionsItem void menu_add(MenuItem item) { // You can add a MenuItem parameter to access it } }
或者:
@EActivity
@OptionsMenu({R.menu.my_menu1, R.menu.my_menu2}) public class MyActivity extends Activity { }
 
@Background
執行:
void myMethod() { someBackgroundWork("hello", 42); } @Background void someBackgroundWork(String aParam, long anotherParam) { [...] }
取消:
void myMethod() { someCancellableBackground("hello", 42); [...] boolean mayInterruptIfRunning = true; BackgroundExecutor.cancelAll("cancellable_task", mayInterruptIfRunning); } @Background(id="cancellable_task") void someCancellableBackground(String aParam, long anotherParam) { [...] }
非並發執行:
void myMethod() { for (int i = 0; i < 10; i++) someSequentialBackgroundMethod(i); } @Background(serial = "test") void someSequentialBackgroundMethod(int i) { SystemClock.sleep(new Random().nextInt(2000)+1000); Log.d("AA", "value : " + i); }
延遲:
@Background(delay=2000) void doInBackgroundAfterTwoSeconds() { }
 
@UiThread
UI線程:
void myMethod() { doInUiThread("hello", 42); } @UiThread void doInUiThread(String aParam, long anotherParam) { [...] }
延遲:
@UiThread(delay=2000) void doInUiThreadAfterTwoSeconds() { }
優化UI線程:
@UiThread(propagation = Propagation.REUSE) void runInSameThreadIfOnUiThread() { }
進度值改變:
@EActivity
public class MyActivity extends Activity { @Background void doSomeStuffInBackground() { publishProgress(0); // Do some stuff publishProgress(10); // Do some stuff publishProgress(100); } @UiThread void publishProgress(int progress) { // Update progress views } }
@OnActivityResult
@OnActivityResult(REQUEST_CODE) void onResult(int resultCode, Intent data) { } @OnActivityResult(REQUEST_CODE) void onResult(int resultCode) { } @OnActivityResult(ANOTHER_REQUEST_CODE) void onResult(Intent data) { } @OnActivityResult(ANOTHER_REQUEST_CODE) void onResult() { }
以上的注釋用法基本包含了平常程序中的事件綁定,用AndroidAnnotations框架可以專注於做邏輯開發,最主要是簡化代碼編寫,容易維護。
如有問題可以參考官方文檔https://github.com/excilys/androidannotations/wiki/Cookbook
 

Annotation 解析

1 運行時 Annotation 解析

(1) 運行時 Annotation 指 @Retention 為 RUNTIME 的 Annotation,可手動調用下面常用 API 解析

 

method.getAnnotation(AnnotationName.class);
method.getAnnotations();
method.isAnnotationPresent(AnnotationName.class);

其他 @Target 如 Field,Class 方法類似
getAnnotation(AnnotationName.class) 表示得到該 Target 某個 Annotation 的信息,因為一個 Target 可以被多個 Annotation 修飾
getAnnotations() 則表示得到該 Target 所有 Annotation
isAnnotationPresent(AnnotationName.class) 表示該 Target 是否被某個 Annotation 修飾
(2) 解析示例如下:

public static void main(String[] args) {
    try {
        Class cls = Class.forName("cn.trinea.java.test.annotation.App");
        for (Method method : cls.getMethods()) {
            MethodInfo methodInfo = method.getAnnotation(
MethodInfo.class);
            if (methodInfo != null) {
                System.out.println("method name:" + method.getName());
                System.out.println("method author:" + methodInfo.author());
                System.out.println("method version:" + methodInfo.version());
                System.out.println("method date:" + methodInfo.date());
            }
        }
    } catch (ClassNotFoundException e) {
        e.printStackTrace();
    }
}

以之前自定義的 MethodInfo 為例,利用 Target(這里是 Method)getAnnotation 函數得到 Annotation 信息,然后就可以調用 Annotation 的方法得到響應屬性值

 

2 編譯時 Annotation 解析

(1) 編譯時 Annotation 指 @Retention 為 CLASS 的 Annotation,甴 apt(Annotation Processing Tool) 解析自動解析。需要做的
a. 自定義類集成自 AbstractProcessor
b. 重寫其中的 process 函數
這塊很多同學不理解,實際是 apt(Annotation Processing Tool) 在編譯時自動查找所有繼承自 AbstractProcessor 的類,然后調用他們的 process 方法去處理
(2) 假設之前自定義的 MethodInfo 的 @Retention 為 CLASS,解析示例如下:

 

@SupportedAnnotationTypes({ "cn.trinea.java.test.annotation.MethodInfo" })
public class MethodInfoProcessor extends AbstractProcessor {
 
    @Override
    public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment env) {
        HashMap<String, String> map = new HashMap<String, String>();
        for (TypeElement te : annotations) {
            for (Element element : env.getElementsAnnotatedWith(te)) {
                MethodInfo methodInfo = element.getAnnotation(MethodInfo.class);
                map.put(element.getEnclosingElement().toString(), methodInfo.author());
            }
        }
        return false;
    }
} 

SupportedAnnotationTypes 表示這個 Processor 要處理的 Annotation 名字。
process 函數中參數 annotations 表示待處理的 Annotations,參數 env 表示當前或是之前的運行環境
process 函數返回值表示這組 annotations 是否被這個 Processor 接受,如果接受后續子的 rocessor 不會再對這個 Annotations 進行處理

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM