Upgrade to Pro — share decks privately, control downloads, hide ads and more …

GDG Toulouse - Android Annotations

GDG Toulouse - Android Annotations

Romain Piel

April 24, 2013
Tweet

More Decks by Romain Piel

Other Decks in Programming

Transcript

  1. 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
  2. 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); } });
  3. 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); } }
  4. 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);
  5. “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
  6. @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); } }
  7. @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); } }
  8. 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
  9. 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 ...
  10. Basic annotations These annotated classes allow to : • Enhance

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

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

    @UiThread Bye AsyncTask! @Background void someBackgroundWork(String aParam, long anotherParam) { } @UiThread void doInUiThread(String result) { }
  14. 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; }
  15. 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 }
  16. 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
  17. 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.
  18. 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
  19. 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
  20. 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.
  21. 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); ! } }
  22. 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; }
  23. 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) { }
  24. 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 ); } }
  25. 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)); } }