AndroidAnnnotations注入框架使用之注入組件Components(三)

(一).前言:
前面咱們已經對於AndroidAnnotations注入框架的基本介紹項目配置和運行原理作了講解,今天咱們開始具體學習怎麼樣使用這個框架。
(二).@EActivity:
當Activity被使用AndroidAnnotations進行注入的時候,咱們須要使用@EActivity這個注入標籤。這個標籤的參數值必須是一個正確的layout ID(佈局ID),該做爲Activity的佈局(Content View)。固然你也能夠設置該參數值爲空,這表示不設置content view。可是在綁定完成以前咱們必須本身在onCreate()方法中設置佈局(content view)
使用方式以下:java

1
2android

@EActivity(R.layout.dragger_inject_layout)
Public class AnnotationsTestActivity extends BaseActivity{}web

不使用佈局ID的方法以下:數據結構

1
2
3
4
5
6
7app

@EActivity
public class MainActvityextends BaseActivity{
@Override
protected void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}框架

(三).@Application:
3.1.基本使用
自AndroidAnnotations 2.2開始
你可使用@Application來對你的Android Application類進行註解ide

1
2函數

@EApplication
public class FDApplication extendsApplication{}佈局

除了相關聯的views和extras以外,咱們可使用絕大多數AA註解。學習

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

@EApplication
public class MyApplication extends Application {
  public void onCreate() {
    super.onCreate();
    initSomeStuff();
  }
  @SystemService
  NotificationManager notificationManager;
  @Bean
  MyEnhancedDatastore datastore;
  @RestService
  MyService myService;
  @OrmLiteDao(helper = DatabaseHelper.class, model = User.class)
  UserDao userDao;
  @Background
  void initSomeStuff() {
    // init some stuff in background
  }
}

3.2.注入Application類
自AndroidAnnotations 2.1開始
你可使用@App來進行注入Application類

1
2
3
4
5

@EActivity
public class MyActivity extends Activity {
  @App
  MyApplication application;
}

該一樣在任何類型注入組件中進行使用,例如:@EBBean

1
2
3
4
5

@EBean
public class MyBean {
  @App
  MyApplication application;
}

(四).@EBean:
4.1.註解自定義類
咱們能夠對於非Android組件(例如:Activity,Service..)的類使用annotations,只須要使用@EBean來進行註解

1
2
3

@EBean
public class MyClass {
}

【注】:使用@EBean註解的類必須只有一個構造函數,並且這個構造函數必須沒有參數。或者在AndroidAnnotations2.7版本上面,該構造函數能夠只有一個Context上下文引用類型的參數。
4.2.注入類
在另外一個註解類或者Android組件中使用這個註解類,咱們可使用@Bean;

1
2
3
4
5

@EBean
public class MyOtherClass {
  @Bean
  MyClass myClass;
}

同時你能夠實現繼承依賴關係

1
2
3
4
5

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

【注】當你在屬性聲明的地方使用@Bean注入,你總會獲得一個新的實例,除非那個類是一個單例。
值得咱們注意的是,註解生成的子類是final類型的,也就是說咱們不能在繼承生成的類。可是咱們能夠擴展原始的類。擴展出來的類一樣可使用註解。以下:

1
2
3

@EActivity
public class MyChildActivity extends MyActivity {
}

4.3.注入實現類
若是你想在代碼中使用父類或者接口,那麼你能夠在@Bean注入的時候把實現類(implementation class)做爲注入的參數值。

1
2
3
4
5
6
7
8

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

4.4.支持的Annotations
在被@Ebean註解的類中,咱們可使用絕大多數AA(Android平臺) 的Annotations;

1
2
3
4
5
6
7
8

@EBean
public class MyClass {
  @SystemService
  NotificationManager notificationManager;
  @UiThread
  void updateUI() {
  }
}

4.5.支持的和View相關的Annotations
在被@EBean註解的類中 ,咱們可使用和View相關的Annotations(例如:@View,@Click…)

1
2
3
4
5
6
7
8

@EBean
public class MyClass {
  @ViewById
  TextView myTextView;
  @Click(R.id.myButton)
  void handleButtonClick() {
  }
}

4.6.依賴注入以後回調執行相關代碼
當咱們@EBean註解的類的構造函數被執行的時候,它的屬性尚未被注入(初始化),若是在構建的時候,想在依賴注入以後執行相關代碼,你能夠在一些方法上面使用@AfterInject Annotation,以下所示

1
2
3
4
5
6
7
8
9
10
11
12
13
14

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

4.7.做用域
AndroidAnnotations如今提供兩種做用域實例
①:默認的做用域:每次建立都會建立一個新的實例對象
②:單一做用域:第一次建立使用的時候會生成一個新實例,而後該實例會保持,其餘都會使用一樣的實例。

1
2
3

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

(五).@EFragment:
5.1.支持FragmentActivity註解
從AndroidAnnotations2.1版本開始
在AndroidAnnotations2.6版本以前,這是不支持Fragment註解,可是可使用FragmentActivity來代替Activity.

1
2
3

@EActivity(R.id.main)
public class DetailsActivity extends FragmentActivity {
}

5.2.Fragment支持
從AndroidAnnotations2.6版本開始
AndroidAnnotations同時支持android.app.Fragment和android.support.v4.app.Fragment.而且它能夠根據Fragment類型選擇使用正確的APIs
5.3.Fragment註解
咱們可使用@EFragment來對Fragment進行註解.

1
2
3

@EFragment
public class MyFragment extends Fragment {
}

AndroidAnnotations將會生成帶有一個下劃線的子類,例如:MyFragment_。當咱們建立一個新的fragmetns實例的時候,你應該在xml 佈局文件中使用生成的子類,以下:

1
2
3
4
5
6
7
8
9
10
11

<linearlayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="horizontal" >

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

</linearlayout>

建立以下:

1

MyFragment fragment=new MyFragment_();

或者你可使用構建器

1

MyFragment fragmeng=MyFragment_.builder().build();

你同時能夠在Fragment中使用各類其餘類型的註解(annotations)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28

@EFragment
public class MyFragment extends Fragment {
    @Bean
    SomeBean someBean;
    @ViewById
    TextView myTextView;
    @App
    MyApplication customApplication;
    @SystemService
    ActivityManager activityManager;
    @OrmLiteDao(helper = DatabaseHelper.class, model = User.class)
    UserDao userDao;
    @Click
    void myButton() {
    }
    @UiThread
    void uiThread() {
    }
    @AfterInject
    void calledAfterInjection() {
    }
    @AfterViews
    void calledAfterViewInjection() {
    }
    @Receiver(actions = "org.androidannotations.ACTION_1")
    protected void onAction1() {
    }
}

5.4.Fragment佈局
Fragment獲取view的標準的方法是重寫onCreateView()方法

1
2
3
4
5
6
7

@EFragment
public class MyFragment extends Fragment {
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.my_fragment_layout, container, false);
        return view;
    }
}

你能夠設置@EFragment的參數值,來讓AndroidAnnotations來進行處理佈局

1
2
3

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

若是你須要重寫onCreateView()方法,例如由於你須要訪問savedInstanceState,此時你仍然可讓AndroidAnnotations來處理佈局建立,而且return null

1
2
3
4
5
6

@EFragment(R.layout.my_fragment_layout)
public class MyFragment extends Fragment {
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        return null;
    }
}

5.5.注入Fragments
咱們能夠在類中使用@EActivity,@EFragment,@Eview,@EViewGroup,@EBean,使用@FragmentById或者@FragmentByTag來進行注入fragments。
【注】推薦使用哪一個@FragmentById而不是@FragmentByTag,由於後者沒有編譯時候的驗證。
請注意@FragmentById和@FragmentByTag僅僅能注入fragments而不是建立它們。因此它們只能存在於Activity中

1
2
3
4
5
6
7
8
9
10
11
12
13
14

@EActivity(R.layout.fragments)
public class MyFragmentActivity extends FragmentActivity {
  @FragmentById
  MyFragment myFragment;

  @FragmentById(R.id.myFragment)
  MyFragment myFragment2;

  @FragmentByTag
  MyFragment myFragmentTag;

  @FragmentByTag("myFragmentTag")
  MyFragment myFragmentTag2;
}

 5.6.DialogFragments

        很是惋惜的是,若是你使用@EFragment進行注入,你沒法經過onCreteDialog()方法來建立一個Dialog新的實例。你應該調用super.onCreateDialog(),該該會返回一個Dialog實例。而後你能夠一個@AfterViews注入的方法中設置views。
(六).@EProvider
自AndroidAnnotations2.4開始
你可使用@EProvider來對Android內容提供者進行註解。

1
2
3

@EProvider
public class MyContentProvider extends ContentProvider {
}

除了相關views和extras註解標籤之外,咱們還可使用絕大多數註解。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

@EProvider
public class MyContentProvider extends ContentProvider {

  @SystemService
  NotificationManager notificationManager;

  @Bean
  MyEnhancedDatastore datastore;

  @OrmLiteDao(helper = DatabaseHelper.class, model = User.class)
  UserDao userDao;

  @UiThread
  void showToast() {
    Toast.makeText(getContext().getApplicationContext(), "Hello World!", Toast.LENGTH_LONG).show();
  }
  // ...
}

(七).@EReceiver
7.1.註解廣播接收者
自AndroidAnnotations2.4開始
咱們可使用@EReceiver來對Android廣播接受者進行註解

1
2
3

@EReceiver
public class MyReceiver extends BroadcastReceiver {
}

除了相關views和extras之外,還可使用絕大多數AA註解

1
2
3
4
5
6
7
8
9
10

@EReceiver
public class MyReceiver extends BroadcastReceiver {

  @SystemService
  NotificationManager notificationManager;

  @Bean
  SomeObject someObject;

}

7.2.註解廣播(Action)
自AndroidAnnotations3.2開始
使用@ReceiverAction能夠在一個被註解的廣播接受者中簡單處理廣播
通常狀況下默認方法onReceive()來進行處理廣播,可是咱們能夠經過@RecevierAction加入參數值來傳遞另一個廣播。
使用@ReceiverAction註解的方法可能存在如下這種參數類型:

  1. 在onReceiver(Contenxt context,Intent intent)中的context上下文引用
  2. 在onReceiver(Context context,Intent intent)中的intent
  3. 若是咱們設置@ReceiverAction.Extra的值, 任何被@ReceiverAction.Extra註解的本地android.os.Parcelable或者java.io.Serializable類型的參數。這些參數將會加入到intent得extra中。加入intent.extra中的key的爲@ReceiverAction.Extra中參數值。

看以下例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

@EReceiver
public class MyIntentService extends BroadcastReceiver {

    @ReceiverAction("BROADCAST_ACTION_NAME")
    void mySimpleAction(Intent intent) {
        // ...
    }

    @ReceiverAction
    void myAction(@ReceiverAction.Extra String valueString, Context context) {
        // ...
    }

    @ReceiverAction
    void anotherAction(@ReceiverAction.Extra("specialExtraName") String valueString, @ReceiverAction.Extra long valueLong) {
        // ...
    }

    @Override
    public void onReceive(Context context, Intent intent) {
        // empty, will be overridden in generated subclass
    }
}

【注】由於BroadcastReceiver的onRecevier是一個抽象方法,因此你不得不添加一個空方法的實現。爲了方便起見,AndroidAnnotations框架已經提供AbstractBroadcastReceiver ,該類已經實現了onReceiver()方法,因此你在使用的時候,能夠不實現該方法。
【注】如今咱們能夠在@ReceiverAction參數中加入多個廣播並進行處理,以下:

1
2
3
4

@ReceiverAction({"MULTI_BROADCAST_ACTION1", "MULTI_BROADCAST_ACTION2"})
void multiAction(Intent intent) {
// ...
}

7.3.數據結構(Data Schemes)
咱們可使用dataSchemes參數來設置一個或者多個數據來讓Receiver進行處理

1
2
3
4
5
6
7
8
9
10
11
12
13
14

@EReceiver
public class MyIntentService extends BroadcastReceiver {

  @ReceiverAction(actions = android.content.Intent.VIEW, dataSchemes = "http")
  protected void onHttp() {
    // Will be called when an App wants to open a http website but not for https.
  }

  @ReceiverAction(actions = android.content.Intent.VIEW, dataSchemes = {"http", "https"})
  protected void onHttps() {
    // Will be called when an App wants to open a http or https website.
  }

}

7.4.@Receiver註解說明
在Activity.Fragment,Service,咱們可使用@Receiver註解,而不是直接聲明一個BroadcastReceiver

1
2
3
4
5
6

@EActivity
public class MyActivity extends Activity {
  @Receiver(actions = "org.androidannotations.ACTION_1")
  protected void onAction1() {
  }
}

(八).@EIntentService
自AndroidAnnotations3.0開始
咱們可使用@EIntentService註解的Android IntentService來處理@ServiceAction註解的方法中的Actions。對於此註解咱們一樣可使用除views和extras之外的不少AA註解

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

@EIntentService
public class MyIntentService extends IntentService {

    public MyIntentService() {
        super("MyIntentService");
    }

    @ServiceAction
    void mySimpleAction() {
        // ...
    }

    @ServiceAction
    void myAction(String param) {
        // ...
    }

    @Override
    protected void onHandleIntent(Intent intent) {
        // Do nothing here
    }
}

咱們可使用內部構建器來啓動IntentService

1
2
3

MyIntentService_.intent(getApplication())
.myAction("test")
.start();

若是在構建器重調用了多個Actions,那麼只有最後一個action會被執行。
自AndroidAnnotations3.3開始
【注】由於IntentService的onHandleIntent是一個抽象方法,因此你這邊不得不添加一個空方法實現。爲了方便起見這邊提供了AbstractIntentService,該類實現了抽象方法。當你使用該類的時候,若是不須要你能夠不用實現onHandleIntent。
(九).@EService
自AndroidAnnotations2.4起
你可使用@EService來進行註冊Android Service

1
2
3

@EService
public class MyService extends Service {
}

除了相關的views和extras以外,一樣可使用絕大多數AA註解

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31

@EService
public class MyService extends IntentService {

  @SystemService
  NotificationManager notificationManager;

  @Bean
  MyEnhancedDatastore datastore;

  @RestService
  MyRestClient myRestClient;

  @OrmLiteDao(helper = DatabaseHelper.class, model = User.class)
  UserDao userDao;

  public MyService() {
      super(MyService.class.getSimpleName());
  }

  @Override
  protected void onHandleIntent(Intent intent) {
    // Do some stuff...

    showToast();
  }

  @UiThread
  void showToast() {
    Toast.makeText(getApplicationContext(), "Hello World!", Toast.LENGTH_LONG).show();
  }
}

咱們能夠經過內部構建器來進行打開這個Service

1

MyService_.intent(getApplication()).start();

自AndroidAnnotations3.0起
同時內部構建器也提供stop()方法來進行中止該Service

1

MyService_.intent(getApplication()).stop();

(十).@EView
10.1.注入自定義views
若是你想要建立自定義組件,咱們可使用@EView和@EViewGroup來進行註解
10.2.爲何要使用自定義組件?
在咱們的APP中不少地方咱們可能會複製一樣的佈局代碼,而且我複製和調用相同的代碼來控制這些佈局。基於前面這些緣由
,咱們可使用自定義組件來解決這些問題,讓咱們的工做變得更加輕鬆。
10.3.使用@EView來註解自定義views
自AndroidAnnotations2.4起
咱們只須要建立一個繼承與View的新類,而後在這個View中就可使用annotations了。

1
2
3
4
5
6
7
8
9
10
11
12
13

@EView
public class CustomButton extends Button {

        @App
        MyApplication application;

        @StringRes
        String someStringResource;

    public CustomButton(Context context, AttributeSet attrs) {
        super(context, attrs);
    }
}

如今你就能夠在佈局文件中使用這個View了(【注】不要忘記"_")

1
2
3
4
5
6
7
8
9
10
11
12
13

< ?xml version="1.0" encoding="utf-8"?>
<linearlayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >

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

    <!-- ... -->

</linearlayout>

你也可使用程序化建立方式

1

CustomButton button = CustomButton_.build(context);

10.4.使用@EViewGroup來註解自定義ViewGroups
自AndroidAnnotations2.2起
①.How to create it?
首先咱們須要爲這個組件建立一個佈局文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

< ?xml version="1.0" encoding="utf-8"?>
<merge xmlns:android="http://schemas.android.com/apk/res/android" >
    <imageview android:id="@+id/image"
        android:layout_alignParentRight="true"
        android:layout_alignBottom="@+id/title"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@drawable/check" />

    <textview android:id="@+id/title"
        android:layout_toLeftOf="@+id/image"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:textColor="@android:color/white"
        android:textSize="12pt" />

    <textview android:id="@+id/subtitle"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@+id/title"
        android:textColor="#FFdedede"
        android:textSize="10pt" />
</merge>

【注】你有沒有發現上面的merge標籤?當這個佈局被進行加載的時候,子節點會被直接加入到父節點中,這樣就能夠減小布局層級關係。
正如你看到是這般使用了不少RelativeLayout特殊佈局屬性(layout_alignParentRight,layout_alignBottom,layout_toLeftOf,etc..),這是由於我知道這個佈局會被加載到RelativeLayout中。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

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

就這樣使用便可,是否是很簡單呢?
如今讓咱們來看一下該怎麼樣使用這個自定義組件
②.How to use it?
自定義組件和其餘View控件同樣,在佈局文件中進行聲明(【注】不要忘記控件名稱最後的"_")

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

< ?xml version="1.0" encoding="utf-8"?>
<linearlayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center"
    android:orientation="vertical" >

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

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

由於咱們使用AA框架,因此咱們會很是容易在Activity中獲得這些注入的自定義組件而且去使用它。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

@EActivity(R.layout.main) public class Main extends Activity {     @ViewById     protected TitleWithSubtitle firstTitle, secondTitle, thirdTitle;     @AfterViews     protected void init() {         firstTitle.setTexts("decouple your code",                 "Hide the component logic from the code using it.");         secondTitle.setTexts("write once, reuse anywhere",                 "Declare you component in multiple " +                 "places, just as easily as you " +                 "would put a single basic View.");         thirdTitle.setTexts("Let's get stated!",                 "Let's see how AndroidAnnotations can make it easier!");     } }

相關文章
相關標籤/搜索