AndroidAnnotations for faster development

Writing the same code for each project all over again can be quite tiresome and time-consuming. In this post, I’ll introduce an Android library which could help you get rid of unnecessary boiler-plate code in several common areas of Android app development. The library is called AndroidAnnotations and it will help you develop your applications faster and with less bugs while writing less code at the same time.

AndroidAnnotations library

The AndroidAnnotations library aims at simplifying and speeding-up the development of often repeated parts of code in your projects. It does this by using the Java annotations. The developers just show their intention and then let AndroidAnnotations generate the boiler-plate code at compile time automatically.

Some of the features of the library include dependency injection for views, system services, resources, etc., simplified threading model, event binding without the need for anonymous listener classes, an easy-to-use REST client, etc.

All this is provided with no performance impact at runtime as the code is generated only during the project build and also it uses no code reflection.

Set up

There are a few things you need to do first in order to start using the AndroidAnnotations library. First, the project-scope build.gradle file has to contain the following android-apt plugin dependency:

build.gradle

Java

1

2

3

4

5

6

7

8

9

buildscript{

repositories{

jcenter()

}

dependencies{

classpath'com.android.tools.build:gradle:2.1.2'

classpath'com.neenbedankt.gradle.plugins:android-apt:1.8'

}

}

And the module build.gradle file will look like this with the android-apt plugin applied and library dependencies included:

build.gradle

Java

1

2

3

4

5

6

7

8

9

10

11

12

13

apply plugin:'com.android.application'

apply plugin:'android-apt'

def AAVersion='4.1.0'

android{

...

}

dependencies{

...

apt"org.androidannotations:androidannotations:$AAVersion"

compile"org.androidannotations:androidannotations-api:$AAVersion"

}

After that, sync your project and you’re ready to start enjoying the benefits of fast Android development provided by the AndroidAnnotations library. Now, let’s talk about the enhanced Android components first.

Enhanced components

In order to use the AndroidAnnotations features, all of the main components have to be annotated too (including Activities, Fragments, Services, etc.).

An enhanced Activity class must be annotated by the @EActivity annotation. You can even supply the layout id to be used with your Activity by supplying the annotation argument, e.g. @EActivity(R.layout.activity_main).

Because the generated classes extend your own classes, you also have to modify the name of the Activities in your manifest file. Just add an underscore to the end of the Activity name, like this:

AndroidManifest.xml

Java

1

2

3

4

5

6

<application

...>

<activity android:name=".MainActivity_">

...

</activity>

</application>

Don’t forget that every time you need to reference your component classes, you should use the generated ones (with underscore at the end), otherwise your code won’t work.

Similarly to the enhanced Activity, there is an enhanced Fragment which is created by annotating a Fragment with the @EFragment annotation (you can inject the layout resource id similarly as with the enhanced Activity). Among others there is @EApplication, @EIntentService, @EService, @EView, etc. to be used with the AndroidAnnotations.

Only inside of the enhanced components, you can use any of the annotations available in AndroidAnnotations library.

Injection

AndroidAnnotations library provides ways to easily inject Views, resources, intent extras, Android system services, and many more. Let’s have a look at some of the examples.

View Injection

AndroidAnnotations can help you get rid of the View glue code easily, similarly to other View Dependency Injection libraries like ButterKnife.

Instead of using the findViewById method, use the @ViewById annotation to find the View in layout. You can specify the View ID as an argument or simply omit it. In that case, the field name will be used to identify the View. The field mustn’t have private access for the injection to work.

Java

1

2

3

4

5

@ViewById

TextView title;

@ViewById(R.id.subtitle)

TextView secondaryTitle;

Although injections are always made as soon as possible, you should not refer the injected Views in onCreate method. Instead, use the @AfterViews method annotation to execute its code right after the Views are injected and can be used safely.

Java

1

2

3

4

5

@AfterViews

voidupdateTitles(StringtitleText,StringsubtitleText){

title.setText(titleText);

subtitle.setText(subtitleText);

}

Several Views can be injected at once when using the @ViewsById annotation. Just supply the View IDs as the annotation arguments and apply the annotation on a List of Views, like this:

Java

1

2

@ViewsById({R.id.myTextView1,R.id.myTextView2})

List<TextView>textViews;

Resources injection

The resource annotations indicate that given Activity field should be injected with specified Android resource from your project’s res folder. The resource ID can be passed as an argument of the annotation. In case it’s not, the name of the field will be used to identify the resource.

The resource annotations you can use include: @StringRes, @ColorRes, @AnimationRes, @DimensionRes, @DrawableRes, and many more. Here are some examples of resource annotations used in code:

Java

1

2

3

4

5

6

7

8

9

10

11

12

13

14

@StringRes(R.string.title_text)

Stringtext;

@ColorRes(R.color.backgroundColor)

intbgColor;

@AnimationRes

Animation fadein;

@DimensionRes

floatfontSize;

@DrawableRes(R.drawable.icon)

Drawable icon;

Extras injection

Using the @Extra annotation, you can inject values to Activity fields with the corresponding Extras from the Intent that was used to start the Activity. A nice bonus is that you can then also use the intent builder to pass the Extra values conveniently.

Java

1

2

3

4

5

@Extra("myExtraString")

StringextraString;

/* start the Activity with extras passed */

MainActivity_.intent(this).extraString("This is extra").start();

Fragment Arguments injection

Similarly to passing Extras, you can use the @FragmentArg to inject a Fragment field with the corresponding Fragment argument. As usually, either you set the name as annotation argument or leave it blank for default field name. Again, you can also use the generated convenient methods provided by the Fragment builder to set the Fragment arguments.

Java

1

2

3

4

5

6

7

8

9

10

11

12

13

14

@EFragment

publicclassMyFragmentextendsFragment{

@FragmentArg("myStringArgument")

StringmyMessage;

@FragmentArg

StringanotherStringArgument;

}

/* using the Fragment builder to pass arguments */

MyFragment myFragment=MyFragment_.builder()

.myMessage("Hello")

.anotherStringArgument("World")

.build();

Event binding

AndroidAnnotations library provides a simple way of avoiding anonymous classes with event listeners. A wide range of event annotations is provided. Let’s see examples of the most common ones now.

Click Events

One of the most repeated actions in Android development is defining the click listeners on Views. AndroidAnnotations comes with @Click, @LongClick and @Touch annotations to help you define click, long-click and touch listeners respectively in an enhanced way.

There are several ways you can define a View click listener with the library. Either you supply the View’s ID as an annotation argument, or let the library derive it from the method name, or you can supply the View object as a parameter of the annotated method. Also, you can define a single listener for multiple Views. Code examples follow:

Java

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

@Click(R.id.myButton)

voidmyButtonClicked(){

//...

}

@Click

voidanotherButton(){

//...

}

@Click

voidyetAnotherButton(View clickedView){

//...

}

@Click({R.id.myButton,R.id.myOtherButton})

voidhandlesTwoButtons(){

//...

}

Key Events

Handling key events can be done easily with the @KeyDown, @KeyUp and @KeyLongPress annotations. The usage is similar to previous annotations and should be clear from the code examples:

Java

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

@KeyDown

voidenterPressed(){

//...

}

@KeyUp(KeyEvent.KEYCODE_ESCAPE)

booleanhandleEscapeActionUpEvent(){

//...

returnfalse;

}

@KeyLongPress({KeyEvent.KEYCODE_A,KeyEvent.KEYCODE_B})

voidaOrBKeyLongPress(KeyEvent keyEvent){

//...

}

Menu Events

Adding and handling options menu support with AndroidAnnotations is a matter of using just two annotations. @OptionsMenu lets you specify the menu resource to be used in your Activity and @OptionsItem annotates methods that receive menu selection events.

Here is an example implementation:

Java

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

@EActivity

@OptionsMenu(R.menu.activity_menu)

publicclassMyActivityextendsActivity{

@OptionsMenuItem

MenuItem menuSearch;

@OptionsItem(R.id.menuShare)

voidmyMethod(){

// ...

}

@OptionsItem

booleanhomeSelected(){

// ... for R.id.home item

returntrue;

}

@OptionsItem({R.id.menu_search,R.id.menu_delete})

voidmultipleMenuItems(){

// ...

}

}

Threading

Threading with AndroidAnnotations is simplified greatly. All you really need are the two provided annotations: @Background and @UiThread to make given methods run in a background or UI thread.

To make a method run in a background thread, just add the @Background annotation to it. If you want to cancel a background task later, you can use the optional id field with it. Another useful feature of the @Background annotation is an option to specify a time delay before the background method is run using a delay parameter.

The @UiThread annotation works exactly the same as the @Background one, except for that the annotated method is run on the UI thread. With the two annotations combined, propagating progress of a task running in background is really simple:

Java

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

@EActivity

publicclassMyActivityextendsActivity{

@Background

voiddoInBackground(){

publishProgress(0);

// ...

publishProgress(10);

// ...

publishProgress(100);

}

@UiThread

voidpublishProgress(intprogress){

// Update progress views

}

}

Other annotations

AndroidAnnotations library provides many other features, some of which I’m going to introduce briefly now.

Customizing window features of your Activity can be done using the @WindowFeature annotation. Putting your activity to full-screen mode is done by annotating the Activity with @Fullscreen annotation.

Another provided feature concerns SharedPreferences. The added functionality includes convenient definition and a typesafe usage. First, create an interface annotated with @SharedPref to define the SharedPreference’s variables. Then use the @Pref annotation to get an instance of the generated SharedPreferences helper class (notice the compulsory underscore in the class name).

Java

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

@SharedPref

publicinterfaceMyPrefs{

@DefaultString("John")/* or use a String resource: R.string.john */

Stringname();

@DefaultInt(42)

intage();

longlastUpdated();/* default value is 0 */

}

@EActivity

publicclassMyActivityextendsActivity{

@Pref

MyPrefs_ myPrefs;

}

The usage of the generated SharedPreferences helper class is very intuitive:

Java

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

myPrefs.name().put("John");

// Batch edit

myPrefs.edit()

.name()

.put("John")

.age()

.put(42)

.apply();

// Preference clearing:

myPrefs.clear();

// Check if a value exists:

booleannameExists=myPrefs.name().exists();

// Reading a value

longlast=myPrefs.lastUpdated().get();

// Reading a value and providing a fallback default value

longlast=myPrefs.lastUpdated().getOr(System.currentTimeMillis(););

A lot of additional functionality is provided through the AndoridAnnotations library plugins. These include for example a REST API client or integration with several 3rd party frameworks (such as RoboGuice, OrmLite, Otto event bus, Dagger, etc.).

Conclusion

In this post, I’ve introduced the AndroidAnnotations library which can help you develop Android applications in shorter time and with less boiler-plate code. Among the features it provides, there is dependency injection, event binding, simplified threading model, and many more. For a full list of provided annotations, go to the project’s Wiki on Github.

Post navigation

4 thoughts on “AndroidAnnotations for faster development”

Came across your articles from linked android groups 🙂 Very good articles, keep posting them up. You can call me a beginner and learning a lot from your articles 😀 Would love to get more and more articles at a faster pace.