AndroidAnnotations框架的使用详解

来源:互联网 发布:淘宝投诉商家电话号码 编辑:程序博客网 时间:2024/05/16 16:03

本文转载了两位大神的bog:

AndroidAnnotations是一个能够让你快速进行Android开发的开源框架,它能让你专注于真正重要的地方。

使代码更加精简,使项目更加容易维护,它的目标就是“Fast Android Development.Easy maintainance”。

通过一段时间的使用发现,相比原生的Android开发,确实能够让你少些很多代码,它的首页也给出了一个简单

的例子,通过例子也可以看到代码比之前几乎少写了一半。由于是开源,所以大家都可以直接拿来使用,这里给

出AndroidAnnotations首页 和github上的项目地址AndroidAnnotations Github。

至于使用这个开源框架有什么好处(只有不到50k大小),我这里就不详细翻译github上的介绍了,就简单说

一下特性:

1、使用依赖注入(Dependency Injection)#本博接来下几篇的文章将要介绍的开源组件都使用DI, 不熟悉

的可以了解一下Inversion of Control(IoC)

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

3、事件绑定(Event binding)

4、REST Client

5、No Magic  [不知道为什么这样称呼,直译过来就是:无魔法,它的意思是:AndroidAnnotations在编译

的时候会产生一个子类(接下来你会明白),你查看这个子类,可以看到它是如何工作的]


环境的配置这里就不讲了,github上已经有比较详细的介绍,这也不是本文的重点,本文重点在简单介绍一下

AndroidAnnotations的简单使用及和其他类似框架(BufferKnife)的不同。

我们先来看一看使用AndroidAnnotations时是如何创建Activity的:

[java] view plain copy
 print?在CODE上查看代码片派生到我的代码片
  1. import android.app.Activity;  
  2. import android.widget.EditText;  
  3. import android.widget.TextView;  
  4.   
  5. import com.googlecode.androidannotations.annotations.Click;  
  6. import com.googlecode.androidannotations.annotations.EActivity;  
  7. import com.googlecode.androidannotations.annotations.ViewById;  
  8.   
  9. @EActivity(R.layout.main)  
  10. public class MyActivity extends Activity {  
  11.   
  12.     @ViewById(R.id.myInput)  
  13.     EditText myInput;  
  14.          
  15.     @ViewById(R.id.myTextView)  
  16.     TextView textView;  
  17.           
  18.     @Click  
  19.     void myButton() {  
  20.          String name = myInput.getText().toString();  
  21.          textView.setText("Hello "+name);  
  22.     }  
  23. }  

从上边的代码中,我们可以看到使用了@EActivity、@ViewById、@Click三个annotation(注释),当然它还提供

了其他很多annotation,这里我就结合这段代码介绍一下这个三个。首先@EActivity后必须要有一个layout id 来表示这

个Activity所使用的布局,远来的onCreate方法就不用了,很明显这样可以让我们少写一些代码;@ViewById 就和原来

的findViewById()方法一样,值得注意的是:@ViewById后的id是可以不写的,条件是控件变量名称要与xml中定义的id

必须一致,也就是说 当我在xml文件中定义的TextView的id必须是:android:id="@+id/textView" . 这样我们在@ViewById

后就不用再写括号了,直接写

[html] view plain copy
 print?在CODE上查看代码片派生到我的代码片
  1. @ViewById  
  2. TextView textView;  

就可以了。但是这样会有一个问题,运行时就会报出:NullPointerException的错误,我们就不能在myButton()方法中

直接使用,而是要在@AfterView注释的方法中使用

[java] view plain copy
 print?在CODE上查看代码片派生到我的代码片
  1. @AfterView  
  2. void init(){  
  3.     textView.setText("Hello");  
  4. }  

这样就不会有问题了。对于@Click,方法名和xml文件中的id一样就可以这样写,AndroidAnnotations会自动识别,对于

多个Button,可以写多个@Click,也可以在这样

[java] view plain copy
 print?在CODE上查看代码片派生到我的代码片
  1. @Click({R.id.button1,R.id.button2,R.id.button3})  
  2. void buttonClicked(Button bt){  
  3.     switch(bt.getId()){  
  4.     case R.id.button1:  //  
  5.         break;  
  6.         ...  
  7.     }  
  8. }  

其他的一些内容就这里就不多讲,因为内容东西虽不是很多,但也几乎包含了Android开发所有内容,有兴趣的朋友可

以到github自行学习,如有问题、疑问欢迎交流,共同学习。

至于xml文件,还是和之前一样,没有变化。

最最最要注意的一点就是:使用AndroidAnnotations千万要记得,编译的时候会生成一个子类,这个子类的名称就是在

原来的类之后加了一个下划线“_”,比如这个例子产生的子类名称为“MyActivity_”,这就需要你在注册这个Activity的时候,在

AndroidManifest.xml中将 MyActivity 改为 MyActivity_ ,使用的时候也是使用MyActivity_来表示此类,如从另一个Activity跳转

到此节目就要这样用:

[java] view plain copy
 print?在CODE上查看代码片派生到我的代码片
  1. startActivity(new Intent(this,MyActivity_.class));  

注意,是MyActivity_.class 不是 MyActivity.class;

AndroidAnnotations就介绍到这里,下面再稍微介绍一下github上的一个大牛Jake Wharton(本博接下来会介绍其一些开源组件)


************************************************

************************************************


另外一个大神:


Android 最火的快速开发框架androidannotations配置详解文章中有eclipse配置步骤,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_();

普通类:

@EBeanpublic class MyClass {}


注意:这个类必须仅仅只能有一个构造函数,参数最多有一个context。

Activity中使用:

@EActivitypublic class MyActivity extends Activity {  @Bean  MyOtherClass myOtherClass;}

也可以用来声明接口:

@Bean(MyImplementation.class)    MyInterface myInterface;

在普通类中还可以注入根环境:

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

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

@EApplicationpublic class MyApplication extends Application {}

Activity中使用:
@EActivitypublic class MyActivity extends Activity {  @App  MyApplication application;}

@EService
@EServicepublic class MyService extends Service {}

跳转service:
MyService_.intent(getApplication()).start();

停止service:
MyService_.intent(getApplication()).stop();

@EReceiver
@EReceiverpublic class MyReceiver extends BroadcastReceiver {}

@Receiver
可以替代声明BroadcastReceiver
@EActivitypublic class MyActivity extends Activity {  @Receiver(actions = "org.androidannotations.ACTION_1")  protected void onAction1() {  }}

@EProvider
@EProviderpublic class MyContentProvider extends ContentProvider {}

@ViewById
@EActivitypublic 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
@EActivitypublic class MyActivity extends Activity {  @StringRes(R.string.hello)  String myHelloString;//不能设置成私有变量  @StringRes  String hello;}

@ColorRes
@EActivitypublic class MyActivity extends Activity {  @ColorRes(R.color.backgroundColor)  int someColor;  @ColorRes  int backgroundColor;}

@AnimationRes
@EActivitypublic class MyActivity extends Activity {  @AnimationRes(R.anim.fadein)  XmlResourceParser xmlResAnim;  @AnimationRes  Animation fadein;}

@DimensionRes
@EActivitypublic class MyActivity extends Activity {  @DimensionRes(R.dimen.fontsize)  float fontSizeDimension;  @DimensionRes  float fontsize;}

@DImensionPixelOffsetRes
@EActivitypublic class MyActivity extends Activity {  @DimensionPixelOffsetRes(R.string.fontsize)  int fontSizeDimension;  @DimensionPixelOffsetRes  int fontsize;}

@DimensionPixelSizeRes
@EActivitypublic 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
@EActivitypublic class MyActivity extends Activity {  @Extra("myStringExtra")  String myMessage;  @Extra("myDateExtra")  Date myDateExtraWithDefaultValue = new Date();}

或者:
@EActivitypublic class MyActivity extends Activity {  // The name of the extra will be "myMessage",名字必须一致  @Extra  String myMessage;}

传值:
MyActivity_.intent().myMessage("hello").start() ;

@SystemService
@EActivitypublic class MyActivity extends Activity {//  @SystemService  NotificationManager notificationManager;}

@HtmlRes
@EActivitypublic 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
@EActivitypublic 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
@HttpsClientHttpClient httpsClient;

示例:
@EActivitypublic 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
@EFragmentpublic 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() {    [...]}@Clickvoid anotherButton() {//如果不指定则函数名和id对应    [...]}@Clickvoid 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);}@Backgroundvoid 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);}@UiThreadvoid doInUiThread(String aParam, long anotherParam) {    [...]}

延迟:
@UiThread(delay=2000)void doInUiThreadAfterTwoSeconds() {}

优化UI线程:
@UiThread(propagation = Propagation.REUSE)void runInSameThreadIfOnUiThread() {}

进度值改变:
@EActivitypublic 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,
或者留言。转载务必注明出处。



0 0
原创粉丝点击