Slide 1

Slide 1 text

AndroidAnnotations Efficient code for Android Romain Piel Android developer at MPme 1830 WEN 24 APR 2013

Slide 2

Slide 2 text

Who am I ? • Android addict since 2010 • Developed multiple apps • Post Office UK, Kiss Kube, Robin for App.net... • Android developer for MPme in London

Slide 3

Slide 3 text

Tonight Android, what’s not handy AndroidAnnotations diet Android and annotations

Slide 4

Slide 4 text

Android, what’s not handy

Slide 5

Slide 5 text

Android, what’s not handy Actions on UI elements TextView myTextView = (TextView)findViewById(R.id.someId); ((Button)findViewById(R.id.someOtherId)).onClick(new OnClickListener() { @Override public void onClick(View v) { handler.postDelayed(new Runnable() { @Override public void run() { Toast.make("sup?", Toast.LENGTH_SHORT).show(); } }, 500); } });

Slide 6

Slide 6 text

Android, what’s not handy AsyncTasks class MakeCoffeeTask extends AsyncTask { @Override protected Coffee doInBackground(String... params) { String brand = params[0]; Boolean withSugar = params[1]; Coffee coffee = makeCoffee(coffeeBrand, withSugar); return coffee; } @Override protected void onPostExecute(Coffee result) { drinkCoffee(result); } }

Slide 7

Slide 7 text

Android, what’s not handy And many other things... @Override public void onSaveInstanceState(Bundle bundle) { super.onSaveInstanceState(bundle); bundle.putSerializable("items", items); } @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); if (savedInstanceState != null && savedInstanceState.containsKey("items")) { items = ((ArrayList ) savedInstanceState.getSerializable("items")); } } ClipboardManager clipboardManager = (ClipboardManager) getSystemService(CLIPBOARD_SERVICE);

Slide 8

Slide 8 text

Consequences Your code You

Slide 9

Slide 9 text

“The ratio of time spent reading (code) versus writing is well over 10 to 1 (therefore) making it easy to read makes it easier to write.” Robert C. Martin

Slide 10

Slide 10 text

AndroidAnnotations diet By Pierre-Yves Ricau and 18 other contributors https://github.com/excilys/androidannotations

Slide 11

Slide 11 text

@EActivity(R.layout.translate) public class TranslateActivity extends Activity { @ViewById EditText textInput; @ViewById(R.id.myTextView) TextView result; @AnimationRes Animation fadeIn; @Click void doTranslate() { translateInBackground(textInput.getText().toString()); } @Background void translateInBackground(String textToTranslate) { String translatedText = callGoogleTranslate(textToTranslate); showResult(translatedText); } @UiThread void showResult(String translatedText) { result.setText(translatedText); result.startAnimation(fadeIn); } } View injection Mission : Simplify developers’ life Resource injection Events Threads Layout @EActivity(R.layout.translate) public class TranslateActivity extends Activity { @ViewById EditText textInput; @ViewById(R.id.myTextView) TextView result; @AnimationRes Animation fadeIn; @Click void doTranslate() { translateInBackground(textInput.getText().toSt } @Background void translateInBackground(String textToTranslate) String translatedText = callGoogleTranslate(te showResult(translatedText); } @UiThread void showResult(String translatedText) { result.setText(translatedText); result.startAnimation(fadeIn); } }

Slide 12

Slide 12 text

@EActivity(R.layout.translate) public class TranslateActivity extends Activity { @ViewById EditText textInput; @ViewById(R.id.myTextView) TextView result; @AnimationRes Animation fadeIn; @Click void doTranslate() { translateInBackground(textInput.getText().toS } @Background void translateInBackground(String textToTranslate) String translatedText = callGoogleTranslate(t showResult(translatedText); } @UiThread void showResult(String translatedText) { result.setText(translatedText); result.startAnimation(fadeIn); View injection Resource injection Events Threads Layout @EActivity(R.layout.translate) public class TranslateActivity extends Activity { @ViewById EditText textInput; @ViewById(R.id.myTextView) TextView result; @AnimationRes Animation fadeIn; @Click void doTranslate() { translateInBackground(textInput.getText().toSt } @Background void translateInBackground(String textToTranslate) String translatedText = callGoogleTranslate(te showResult(translatedText); } @UiThread void showResult(String translatedText) { result.setText(translatedText); result.startAnimation(fadeIn); } }

Slide 13

Slide 13 text

More than 80 annotations: • Enhanced components • Activity, Service, etc... • Injections • Views, resources, dependencies... • Event binding • Simple threading Easy integration with other libraries Mission : Simplify developers’ life

Slide 14

Slide 14 text

Basic annotations @EActivity(R.layout.translate) public final class TranslateActivity { } Activities are annotated @EActivity Annotations exist for every main components @EService @EReceiver @EApplication @EFragment @EProvider ...

Slide 15

Slide 15 text

Basic annotations These annotated classes allow to : • Enhance basic components • Layout injections • Fullscreen activities, etc... • Add annotations on attributes and methods

Slide 16

Slide 16 text

Internal annotations - Injections • View injections • Resource injections • System service injections @ViewById(R.id.myTextView) TextView result; @AnimationRes Animation fadeIn; @SystemService NotificationManager notificationManager;

Slide 17

Slide 17 text

Internal annotations - Injections Annotated attributes cannot be directly used in constructors or in onCreate() @AfterInject : non view attributes are injected @AfterViews : views are injected @AfterInject public void doSomethingAfterInjection() { } @AfterViews public void updateTextWithDate() { result.setText("Date: " + new Date()); }

Slide 18

Slide 18 text

Internal annotations - Threading Annotate you methods with @Background and @UiThread Bye AsyncTask! @Background void someBackgroundWork(String aParam, long anotherParam) { } @UiThread void doInUiThread(String result) { }

Slide 19

Slide 19 text

Custom objects Custom classes can be annotated using @EBean : Then this class can be injected: @EBean public class MyClass { } @EActivity public class MyActivity extends Activity { @Bean MyClass myObject; }

Slide 20

Slide 20 text

Not bad... But how does your thing work?

Slide 21

Slide 21 text

But how does your thing work? Java 6 Annotation Processor Code generation at compile-time Each annotated class will have a generated subclass: public final class TranslateActivity_ extends TranslateActivity { ! // Ugly code you wish you would never have to write again }

Slide 22

Slide 22 text

But how does your thing work? IDE configuration (eclipse) : 1.Add in /libs androidannotations-X.X.X-api.jar 2.Add this jar to the project’s build path 3.Add in a directory /compile-libs the jar androidannotations-X.X.X.jar 4.In project properties: Java Compiler > Annotation Processing Enable annotation processing Java Compiler > Annotation Processing > Factory Path Add the processor androidannotations-X.X.X.jar

Slide 23

Slide 23 text

But watch out! startActivity(new Intent(this, TranslateActivity_.class)); @AfterViews public void updateTextWithDate() { result.setText("Date: " + new Date()); }

Slide 24

Slide 24 text

Any performance impact? Nope Hard work is made during compile time Runtime is not affected

Slide 25

Slide 25 text

Consequences Your code You

Slide 26

Slide 26 text

Using AndroidAnnotations IRL • At start, hard to get into AndroidAnnotations logic. • Then quickly addictive... • A much more readable code. • Encourage to organize the code in modules. • Debugging : no difference. The generated code is not hidden.

Slide 27

Slide 27 text

Using AndroidAnnotations IRL A few limitations: • Generic classes not supported • Not a good idea to integrate inheritance between two annotated classes. • Internal classes can’t be annotated

Slide 28

Slide 28 text

Android and annotations 1. AndroidAnnotations “friends” 2. The others

Slide 29

Slide 29 text

Roboguice Built on top of Google Guice View and dependency injections + Injection more powerful than AndroidAnnotations - Injections are done during runtime ‣ Performance impact - Activities must extend RoboActivity ‣ Issue for using other libraries

Slide 30

Slide 30 text

Dagger Dependencies injection library similar to Google Guice. Like Roboguice, offers more options on dependencies injection than AndroidAnnotation Injections also done during runtime Not Android exclusive but very light. A fast dependency injector for Android and Java.

Slide 31

Slide 31 text

Butter Knife Very simple library for view injections. Very similar to AndroidAnnotations view injection class ExampleActivity extends Activity { ! @InjectView(R.id.title) TextView title; ! @InjectView(R.id.subtitle) TextView subtitle; ! @InjectView(R.id.footer) TextView footer; ! @Override public void onCreate(Bundle savedInstanceState) { ! ! super.onCreate(savedInstanceState); ! ! setContentView(R.layout.simple_activity); ! ! Views.inject(this); ! } }

Slide 32

Slide 32 text

Android and annotations 1. AndroidAnnotations “friends” 2. The others

Slide 33

Slide 33 text

Project lombok Java library based on annotations to simplify the language: @AllArgsConstructor public class MyClass { ! @Getter @Setter private int age = 10; ! @Setter(AccessLevel.PROTECTED) private String name; }

Slide 34

Slide 34 text

Otto Java library based on annotations offering an event bus: Otto An enhanced Guava-based event bus with emphasis on Android support. Bus Post Subscribe bus.post(new AnswerAvailableEvent(42)); @Subscribe public void answerAvailable(AnswerAvailableEvent event) { }

Slide 35

Slide 35 text

Retrofit Java library to implement painlessly a REST client: public class Client { private static final String API_URL = "https://api.github.com"; class Contributor { String login; int contributions; } interface GitHub { @GET("/repos/{owner}/{repo}/contributors") List contributors( @Name("owner") String owner, @Name("repo") String repo ); } }

Slide 36

Slide 36 text

Roboelectric Android oriented library for quick unit testing: @RunWith(RobolectricTestRunner.class) public class HomeActivityTest { ! private HomeActivity activity; private ImageView pivotalLogo; @Before public void setUp() throws Exception { activity = new HomeActivity(); activity.onCreate(null); pivotalLogo = (ImageView) activity.findViewById(R.id.pivotal_logo); } @Test public void shouldHaveALogo() throws Exception { assertThat(pivotalLogo.getVisibility(), equalTo(View.VISIBLE)); assertThat(shadowOf(pivotalLogo).getResourceId(), equalTo(R.drawable.pivotallabs_logo)); } }

Slide 37

Slide 37 text

Conclusion Annotations for: • Readability • Maintainability • Reusability Keep it simple

Slide 38

Slide 38 text

Any questions?