目录

@EBean增强自定义类

原文地址: https://github.com/excilys/androidannotations/wiki/Enhance-custom-classes

加强自定义类

您可以在一个不是一个标准的Android组件(如Activity,Service)的类使用注解@EBean。 你只需要使用@EBean注释这个类即可:

1
2
3
4
@EBean
public class MyClass {

}

一个@EBean注解类必须只有一个构造函数。此构造必须不含参数,或者作为AndroidAnnotations2.7,它在有些语境中的可以有一个参数。

注射增强类

在另一个增强类或增强的Android组件使用增强类,则可以使用@Bean

1
2
3
4
5
6
7
@EBean
public class MyOtherClass {

  @Bean
  MyClass myClass;

}

请注意链的依赖关系:

1
2
3
4
5
6
7
@EActivity
public class MyActivity extends Activity {

  @Bean
  MyOtherClass myOtherClass;

}

在使用@Bean时你总可以获得该类的一个新实例,除非这个类被声明为单例类(a Singleton)后面会讲到。

值得注意的是,生成的子类被加上了final限定,这意味着你不能扩展生成的子类。但是,您可以扩展原有的类和生成的代码将在子类中也同时发生扩展。这适用于每一个注解。 比如下面这个被注解的类,也会有一个子类的注入:

1
2
3
4
@EActivity
public class MyChildActivity extends MyActivity {

}

##在代码区域注入一个接口的实现 如果你想通过其API(无论是超类或接口)来使用你的代码的依赖,可以作为注解@Bean的值参数指定的实现类。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
@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;

}

这样有解耦的作用么?这里的类仍然知道它的依赖实现,但至少使用这些依赖的代码必须依靠API,这是一个有趣的目标。

支持其他注解的使用

您可以在@EBean类使用大多数AA标注:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
@EBean
public class MyClass {

  @SystemService
  NotificationManager notificationManager;

  @UiThread
  void updateUI() {

  }

}

使用View相关的注解

您可以在@EBean类中使用视图相关的注释(@View,@Click…):

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
@EBean
public class MyClass {

  @ViewById
  TextView myTextView;

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

  }

}

注意:这里视图注解相关的控件myTextView和点击方法handleButtonClick() 只有在引用MyClass的Activity里包含相应内容视图中有这个myTextView id 和 R.id.myButton才有效。不然的话,myTextView会默认为空,而handleButtonClick()方法永远也不回被调用。

注射根上下文

你可以注入这就要看你@EBean类,使用@RootContext注解根的Android组件。请注意,它仅在上下文具有正确的类型情况下被注入。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
@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;

}

通过以下Activity引用的MyClass的实例,MyClass的(上文的)service将是null

1
2
3
4
5
6
7
@EActivity
public class MyActivity extends Activity {

  @Bean
  MyClass myClass;

}

##依赖注入后执行代码 当你的@EBean注解类的构造函数被调用时,它的领域还没有被注入了呢。如果您需要在编译时执行代码,依赖注入之后,你应该对用一些方法使用@AfterInject注释。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
@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
  }

}

##警告

如果一个父类和他的子类拥有同名的方法,这些方法被@AfterInject@AfterView 或者@AfterExtras 注解,那么就会出现BUG,详情请见 issue #810。 另外,虽然有关于当我们称之为@AfterViews保证顺序,-Inject或-Extras注解的方法,就不能保证每个具有相同方法名的@AfterXXX注解方法的调用顺序(参见问题#810)。 想知道这些注解之一的方法什么时候被调用,你可以在这里找到的答案

Scopes

AndroidAnnotations目前支持两种范围:

  • 默认范围:在每次被注入的时候新生成一个类的实例对象;
  • 单例范围:在第一次被需要的时候创建一个Bean的实例,它然后被保留,并且在同一实例始终注入。
1
2
3
4
@EBean(scope = Scope.Singleton)
   public class MySingleton {
   
   }

注意:

  • 如果你的bean有一个Singleton范围,它只会保持一个参考应用程序上下文(应该使用context.getApplicationContext()),这是因为它的生活时间比任何Activity/Service 要长,所以它不应该保持一个参考任何此类的Android组件,以避免内存泄漏。
  • 我们还认为应该禁用与Singleton范围@EBean组件注入和查看事件的绑定,完全一样的原因(View参考一个Activity,因此它可能会造成内存泄漏)。