AndroidAnnotations——Enhance custom classes 优化自定义类

Enhance custom classes


Since AndroidAnnotations 2.4

Enhancing custom classes 优化自定义类


You can use annotations in a class that is not a standard Android component (such as an Activity, a Service).
你可以在一个不是标准Android组件(比如Activity,Service)的类中使用注解。

You just need to annotate it with  @EBean:
你只需要使用   @EBean 进行注解:

@EBean
public class MyClass {

}
An  @EBean annotated class must have only one constructor. This constructor must either have no parameters, or, as of  AndroidAnnotations 2.7, it may have one parameter of type Context.
一个用   @EBean   注解的类必须只有一个构造函数。这个构造函数必须是无参的,或者,在 AndroidAnnotations 2.7 以后,可以带一个类型为 Context 的参数。

Injecting enhanced classes 注入优化的类


To use this enhanced class in another enhanced class or in an enhanced Android component, use @Bean:
在其他优化类或者优化的Android组件中,加上 @Bean 注解就可以使用这个优化类。

@EBean
public class MyOtherClass {

  @Bean
  MyClass myClass;

}

Notice how you can chain dependencies:
请注意你怎么才能连接它们的相关性:

@EActivity
public class MyActivity extends Activity {

  @Bean
  MyOtherClass myOtherClass;

}
You always get a  new instance when you use  @Bean on a field, unless that bean is a Singleton (see Scopes below).
当你使用   @Bean   在一个字段上时, 你一直获得一个新的实例。除非这个bean是一个单例(参看下面的作用域)。

It is worth noting that the generated subclasses are final, which means that you can't extend generated classes. However, you can extends original classes and generated code will be also generated for the child class. This works for every annotations.
值得注意的是,生成的子类是final类型的,这意味着你不能继承这些生成的子类。但是,你可以继承原始类,同时这些继承原始类的子类也会获得final子类生成的代码。

For example the following class will also have  myOtherClass injected :
举个例子,下面这个类也会有   myOtherClass   注入进来:

@EActivity
public class MyChildActivity extends MyActivity {

}

Injecting implementations in assignable fields 注入实现到指定的字段

Since AndroidAnnotations 2.5


If you want to use a dependency in your code through its API (either a superclass or an interface), you can specify the implementation class as the value parameter of the  @Bean annotation.
假如你想在代码中通过API使用一个依赖关系(不论是父类还是接口),你可以指定实现类作为   @Bean   注入的参数值。

@EActivity
public class MyActivity extends Activity {

    /* A MyImplementation instance will be injected.  * MyImplementation must be annotated with @EBean and implement MyInterface. */
    @Bean(MyImplementation.class)
    MyInterface myInterface;

}

Does that provide decoupling advantages ? Well, the class still knows about its dependencies implementation, but at least the code using those dependencies has to rely on the API, which is an interesting goal.那样是不是提供了松耦合的优势呢?其实,这个类还是知道它自己的依赖实现,但是至少代码使用这些依赖必须依靠API,这其实是一个很有意思的目的。

Supported annotations 所支持的注解


You can use most AA annotations in an  @EBean class:
可以   @EBean   类中使用大部分的AA注解:

@EBean
public class MyClass {

  @SystemService
  NotificationManager notificationManager;

  @UiThread
  void updateUI() {

  }

}

View related annotations 和视图相关的注解


You can use view related annotations ( @View,  @Click...) in your  @EBean class:
可以   @EBean   类中 使用和视图相关   ( @View @Click ...)   的注解:

@EBean
public class MyClass {

  @ViewById
  TextView myTextView;

  @Click(R.id.myButton)
  void handleButtonClick() {

  }

}
Notice that this will only work if the root Android component that depends on  MyClass is an activity with a layout that contains the needed views. Otherwise,  myTextView will be null, and handleButtonClick() will never be called.
请注意,只有当依赖于   MyClass   的Android根组件是一个activity,并且它的布局文件包含了所需的视图,这些注解才会生效。否则,   myTextView   会为null, handleButtonClick()   也永远不会被调用。

Injecting the root context 注入root context


You can inject the root Android component that depends on your  @EBean class, using the @RootContext annotation. Please notice that it only gets injected if the context has the right type.
你可以使用 @RootContext   注解注入依赖你   @EBean   类的Android根组件。请注意,只有当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;

}

In the  MyClass instance referenced by the following activity, the  service field of  MyClass (see above) will be  null.
在下面这个activity中有一个上述的   MyClass   实例,它的字段   service   将为空。

@EActivity
public class MyActivity extends Activity {

  @Bean
  MyClass myClass;

}

Executing code after dependency injection 在依赖注入后执行代码


When the constructor of your  @EBean annotated class is called, it's fields have not been injected yet. If you need to execute code at build time, after dependency injection, you should use the @AfterInject annotation on some methods.
当你的   @EBean   注解类的构造器被调用后,它的字段还没有注入进来。假如你需要在构建项目的时候执行代码,那么在依赖注入后,你需要添加使用 @AfterInject   注解的方法。

@EBean
public class MyClass {

  @SystemService
  NotificationManager notificationManager;

  @Bean
  MyOtherClass dependency;

  public MyClass() {
    // notificationManager and dependency are null
  }

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

}

Note : If the parent and child classes have  @AfterViews annotated methods with the same name, the generated code will be buggy. See  issue #591 for more details.
注意:如果父类和子类的   @AfterViews   注解方法使用相同的名字,生成的代码会有bug。详情参见   issue #591

Scopes 作用域

Since AndroidAnnotations 2.5


AndroidAnnotations currently support two scopes:
AndroidAnnotations现在支持两个作用域:

  • the default scope: a new bean instance is created each time a bean must be injected
  • 默认作用域:每次当新的bean实例创建时都需要注入一个bean
  • the singleton scope: a new instance of the bean is created the first time it is needed. It is then retained and the same instance is always injected.
  • 单例作用域:只有第一次才创建bean实例。然后之后一直使用同一个实例注入。
@EBean(scope = Scope.Singleton)
public class MySingleton {

}

Caution警告

  • If your bean has a Singleton scope, it will only keep a reference to the application context (using context.getApplicationContext(). That's because it lives longer than any activity / service, so it shouldn't keep a reference to any such Android component, to avoid memory leaks.
  • 假如你的bean有了 Singleton 作用域,它将保持application context的引用(使用context.getApplicationContext()。那是因为它是生命周期比任何activity或者service都长,所以它应该在任何Android组件中保留引用,避免引起内存泄漏。
  • We also disable view injection and view event binding in @EBean components withSingleton scope, for the exact same reason (views have a reference to the activity, which may therefore create a leak).
同样,我们也在使用 Singleton 作用域的   @EBean   组件中禁用了视图注入和视图事件绑定(视图拥有activity的引用,因此有可能产生内存泄漏)。

本文档的简单示例下载

你可能感兴趣的:(AndroidAnnotations——Enhance custom classes 优化自定义类)