Save 37% off PRO during our Black Friday Sale! »

GDG Toulouse - Android Annotations

GDG Toulouse - Android Annotations

6cd7230b4e87700f07a7bd5d28c54eb3?s=128

Romain Piel

April 24, 2013
Tweet

Transcript

  1. AndroidAnnotations Efficient code for Android Romain Piel Android developer at

    MPme 1830 WEN 24 APR 2013
  2. 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
  3. Tonight Android, what’s not handy AndroidAnnotations diet Android and annotations

  4. Android, what’s not handy

  5. 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); } });
  6. Android, what’s not handy AsyncTasks class MakeCoffeeTask extends AsyncTask<String, Void,

    Coffee> { @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); } }
  7. 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<String> ) savedInstanceState.getSerializable("items")); } } ClipboardManager clipboardManager = (ClipboardManager) getSystemService(CLIPBOARD_SERVICE);
  8. Consequences Your code You

  9. “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
  10. AndroidAnnotations diet By Pierre-Yves Ricau and 18 other contributors https://github.com/excilys/androidannotations

  11. @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); } }
  12. @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); } }
  13. 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
  14. 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 ...
  15. Basic annotations These annotated classes allow to : • Enhance

    basic components • Layout injections • Fullscreen activities, etc... • Add annotations on attributes and methods
  16. Internal annotations - Injections • View injections • Resource injections

    • System service injections @ViewById(R.id.myTextView) TextView result; @AnimationRes Animation fadeIn; @SystemService NotificationManager notificationManager;
  17. 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()); }
  18. Internal annotations - Threading Annotate you methods with @Background and

    @UiThread Bye AsyncTask! @Background void someBackgroundWork(String aParam, long anotherParam) { } @UiThread void doInUiThread(String result) { }
  19. 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; }
  20. Not bad... But how does your thing work?

  21. 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 }
  22. 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
  23. But watch out! <activity android:name=".MyActivity_" /> startActivity(new Intent(this, TranslateActivity_.class)); @AfterViews

    public void updateTextWithDate() { result.setText("Date: " + new Date()); }
  24. Any performance impact? Nope Hard work is made during compile

    time Runtime is not affected
  25. Consequences Your code You

  26. 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.
  27. 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
  28. Android and annotations 1. AndroidAnnotations “friends” 2. The others

  29. 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
  30. 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.
  31. 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); ! } }
  32. Android and annotations 1. AndroidAnnotations “friends” 2. The others

  33. 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; }
  34. 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) { }
  35. 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<Contributor> contributors( @Name("owner") String owner, @Name("repo") String repo ); } }
  36. 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)); } }
  37. Conclusion Annotations for: • Readability • Maintainability • Reusability Keep

    it simple
  38. Any questions?