Android开发技能知识点

Android Annotation 注解框架

2017-03-20  本文已影响998人  黄海佳
一、Annotation简单介绍

AndroidAnnotations是一个能够让你快速进行Android开发的注释、注解开源框架。使代码更加精简,使项目更加容易维护,与相比原生的Android开发,能够让你少些很多代码。原理是给某个东西打上一个身份标识,告诉ide说,这个东西是要进行id绑定的,那个东西是参数来着。。。
官网如下:官网

Annotation的主要完成的工作如下

1、使用依赖注入(Dependency Injection)

2、简化的线程模型(Simplified threading model)

3、事件绑定(Event binding)

4、REST Client

5、No Magic

Paste_Image.png
二、相关专有名词解释
1. 元数据(metadata)

元数据由metadata译来,所谓的元数据就是“关于数据的数据”,更通俗的说就是描述数据的数据,对数据及信息资源的描述性信息.比如说一个文本文件,有创建时间,创建人,文件大小等数据,这都可以理解为是元数据。

在java中,元数据以标签的形式存在java代码中,它的存在并不影响程序代码的编译和执行,通常它被用来生成其它的文件或运行时知道被运行代码的描述信息。java当中的javadoc和注解都属于元数据。

2 元注解

元注解就是定义注解的注解,是java提供给我们用于定义注解的基本注解.在java.lang.annotation包中我们可以看到目前元注解共有以下几个。
@Retention
@Target
@Inherited
@Documented
@interface

3. 注解处理器

注解处理器是javac的一个工具,它用来在编译时扫描和处理注解(Annotation)。你可以自定义注解,并注册到相应的注解处理器,由注解处理器来处理你的注解。一个注解的注解处理器,以Java代码(或者编译过的字节码)作为输入,生成文件(通常是.java文件)作为输出。这些生成的Java代码是在生成的.java文件中,所以你不能修改已经存在的Java类,例如向已有的类中添加方法。这些生成的Java文件,会同其他普通的手动编写的Java源代码一样被javac编译。

三、Annotation相关方法

Annotation支持事件的绑定,其中包括对UI控件的声明,对Activity之间,Fragment之间参数的声明,对于一些数值进行非空的声明等等。

(一)UI的绑定以及事件绑定
(二)简化线程

在Android中,为了不阻塞主进程,所以所有的耗时操作是不予许在UI线程进行的,不然就会Crash。但是在开发当中却是需要大量的时候耗时操作的,例如对磁盘的读写操作,进行网络的请求,对于图片的操作等等,同时往往在进行这样的耗时操作的时候又会伴随的必须、只能在UI线程进行的操作。例如取回网络数据,进行解析之后要更新UI界面。这样来回的切换会造成开发的不变以及大量的代码冗余。尽管java已经有成熟的thread以及比较方便的AnsyncTask。但是所有的都不如一个注释方便。

(三)对于网络请求的操作

在Annotation中,我们可以把所有网络有关的操作集中成一个工具类:
get、post、put、delete等操作。

@EActivity
值得注意的是,Annotation的工作方式是经过编译之后,生成一个类名相同而且带有_的文件,例如LoginActivity会变成LoginActivity_,因此在Manifest中声明Activity的时候是必须带有_的,不然会报错。

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

}


-------------------------不带layout-------------------------
@EActivity
public class MyActivity extends Activity {

  @Bean
  MyOtherClass myOtherClass;

}

@fragment

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

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

-------------------------创建-------------------------
MyFragment fragment = new MyFragment_();



@Bean

-------------------------普通类-------------------------
@EBean
public class MyClass {
    //注意:这个类必须仅仅只能有一个构造函数,参数最多有一个context。
}


-------------------------普通类注入根环境-------------------------
@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;

}


-------------------单例类需要如下声明----------------
@EBean(scope = Scope.Singleton)
public class MySingleton {
//注意:在单例类里面不可以注入view和事件绑定,因为单例的生命周期比Activity和Service的要长,以免发生内存溢出。
}


-------------------------接口-------------------------
@Bean(MyImplementation.class)
 MyInterface myInterface;

@AfterInject

  @AfterInject
  public void doSomethingAfterInjection() {
    // notificationManager and dependency are set
    //类创建时期做一些操作
  }

@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


@EActivity
public class MyActivity extends Activity {

  @Receiver(actions = "org.androidannotations.ACTION_1")
  protected void onAction1() {
    //可以替代声明BroadcastReceiver
  }

}

@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;
}

@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 {

  @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()
 //http://developer.android.com/reference/android/app/Activity.html#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) {
        LogUtils("HTTP status " + resp.getStatusLine().getStatusCode());
    }
}

@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) {
    [...]
}

其他点击事件

Item clicks with @ItemClick

Long item clicks with @ItemLongClick

Item selection with @ItemSelect

Clicks with @Click

Long clicks with @LongClick

Touches with @Touch

@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) {

    }

}

--------------------------------------------
@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 和 @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 @AfterTextChange

@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
 }

@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

@Backgroud

void toDoSomeHeavyWork(){

  //进行一些耗时的操作

setView();//需要进行UI操作的时候

}

@UIThread

void setView(){

  //进行一些只能在UI主线程上进行的操作

}


---------------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() {
 }
四、关于RetentionPolicy

** CLASS:** 编译时注解
** RUNTIME:** 运行时注解
** SOURCE:** 源码注解

不同的注解有各自的生命周期,根据你实际使用来确定使用哪种类型的注解。

五、@Target ( 目标)

用于指定被修饰的Annotation能用于修饰哪些程序单元,只能修饰Annotation定义。它包含一个名为value的成员变量,取值如下:

@Target(ElementType.ANNOTATION_TYPE):指定该该策略的Annotation只能修饰Annotation.
@Target(ElementType.TYPE) //接口、类、枚举、注解
@Target(ElementType.FIELD) //成员变量(字段、枚举的常量)
@Target(ElementType.METHOD) //方法
@Target(ElementType.PARAMETER) //方法参数
@Target(ElementType.CONSTRUCTOR) //构造函数
@Target(ElementType.LOCAL_VARIABLE)//局部变量
@Target(ElementType.PACKAGE) ///修饰包定义
@Target(ElementType.TYPE_PARAMETER) //java8新增,后面Type Annotation有介绍
@Target(ElementType.TYPE_USE) ///java8新增,后面Type Annotation有介绍
@Target(ElementType.FIELD)
public @interface ActionListenerFor{}

六、@Documented

用于指定被修饰的Annotation将被javadoc工具提取成文档。即说明该注解将被包含在javadoc中。

七、@Inherited

用于指定被修饰的Annotation具有继承性。即子类可以继承父类中的该注解。---》注解@WW被元注解@Inherited修饰,把@WW添加在类Base上,则Base的所有子类也将默认使用@WW注解。

上一篇下一篇

猜你喜欢

热点阅读