There are a few libraries for Android, which implement a lot of widely used features and concepts from the well known Java ecosystem for less powerful devices. Some of then provide the base for my Android technology stack, which I would like to present today.
Android Annotations (http://androidannotations.org )
Android Annotations provides a whole lot of features, which really provide value for the developer in terms of readability and maintainability. The main features are:
- Dependency injection
- Event handling
- Simple threading
- Consuming REST APIs
Android Annotations uses APT and generates optimized classes at compile time. This was a design choice to reduce the launch time (respectively don’t increase it) at startup and prevent sluggish runtime behavior. It’s simple to include in your build.gradle files (both the app’s build.gradle and the project level build.gradle):
1buildscript { 2 // … 3 dependencies { 4 classpath 'com.android.tools.build:gradle:2.2.3' 5 classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8' 6 } 7 // … 8}
build.gradle (Projekt)
1apply plugin: 'android-apt' 2 3android { 4 // … 5} 6 7dependencies { 8 // … 9 apt('org.androidannotations:androidannotations:4.2.0') 10 compile('org.androidannotations:androidannotations-api:4.2.0') 11}
build.gradle (App)
1public class ExampleActivity extends Activity {
2 private Button exampleButton;
3
4 @Override
5 protected void onCreate(Bundle savedInstanceState) {
6 super.onCreate(savedInstanceState);
7 setContentView(R.layout.layout_example);
8 exampleButton = (Button) findViewById(R.id.exampleButton);
9 exampleButton.setOnClickListener(new OnClickListener() {
10 @Override
11
public void onClick(View view) {
12
// do something
13
}
14 });
15 }
16}
Vanilla Android
1@EActivity(R.layout.layout_example);
2public class ExampleActivity extends Activity {
3 @ViewById
4 Button exampleButton;
5
6 @Click
7 void exampleButtonWasClicked() {
8 // do something
9 }
10}
Android with Android Annotations
When Android Annotations provides to much features which are not used, one can use a combination of Butterknife (view injection, http://jakewharton.github.io/butterknife), Dagger (dependency injection, https://google.github.io/dagger) and Retrofit (REST client, https://square.github.io/retrofit).
EventBus (http://greenrobot.org/eventbus )
To decouple an Activity or Fragment from the business logic, it may be worth to have a look at the publish/subscribe pattern and an established library called EventBus from greenrobot:
1apply plugin: 'android-apt' 2 3android { 4 // … 5} 6 7dependencies { 8 // … 9 compile('org.greenrobot:eventbus:3.0.0') 10}
build.gradle (App)
1public class ExampleActivity extends Activity {
2 protected final EventBus eventBus = EventBus.getDefault();
3
4 @Override
5 protected void onStart() {
6 super.onStart();
7 eventBus.register(this);
8 }
9
10 @Override
11 protected void onStop() {
12 super.onStop();
13 eventBus.unregister(this);
14 }
15}
Other steps, like publishing an event and subscribing to it, can be found in the EventBus documentation at GitHub .
IcePick (https://github.com/frankiesardo/icepick )
IcePick reduces the boilerplate code which arises as a result of having to manage instance states from activities and fragments. This is accomplished by by the means of APT and code generation (remember Android Annotations?).
1@EActivity(R.layout.layout_example);
2public class ExampleActivity extends Activity {
3
4 @State
5 String exampleText;
6
7 @ViewById
8 Button exampleButton;
9
10 @Click
11 void exampleButtonWasClicked() {
12 // do something
13 }
14
15 @Override
16 protected void onSaveInstanceState(Bundle outState) {
17
super.onSaveInstanceState(outState);
18 Icepick.saveInstanceState(this, outState);
19
}
20
21 @Override
22
protected void onRestoreInstanceState(Bundle savedInstanceState) {
23
super.onRestoreInstanceState(savedInstanceState);
24
Icepick.restoreInstanceState(this, savedInstanceState);
25 }
26}
The content of exampleText will be restored on all configuration change events (i.e. OrientationChanges).
LeakCanary (https://github.com/square/leakcanary )
Memory leaks are not a harmless crime! In order to find them you can use the library LeakCanary, which – once it is initialized in the Application implementation, shows a notification when it discovered a memory leak while testing the debug build.
1public class ExampleApplication extends Application {
2
3 @Override
4 public void onCreate() {
5 super.onCreate();
6 if (LeakCanary.isInAnalyzerProcess(this)) {
7 // This process is dedicated to LeakCanary for heap analysis.
8 // You should not init your app in this process.
9 return;
10 }
11 LeakCanary.install(this);
12 }
13}
Espresso (https://developer.android.com/topic/libraries/testing-support-library/index.html#Espresso )
Espresso is a test framework included in the Android test support libraries. It provides a DSL for automated UI tests. The implemented concepts (based on JUnit, JUnit TestRules, Matchers) are well known to developers, so this framework should be easy to learn. Espresso runs on emulators and real devices.
Conclusion
This is just a small, selected list of libraries, which focusses on code quality, maintainability and testability.
A few rough edges, which sometimes make Android development so cumbersome, are smoothed over.
Praise the community!
Which libraries are you using? Leave a comment and discuss this article with me.
More articles
fromSascha Masanneck
Your job at codecentric?
Jobs
Agile Developer und Consultant (w/d/m)
Alle Standorte
More articles in this subject area
Discover exciting further topics and let the codecentric world inspire you.
Gemeinsam bessere Projekte umsetzen.
Wir helfen deinem Unternehmen.
Du stehst vor einer großen IT-Herausforderung? Wir sorgen für eine maßgeschneiderte Unterstützung. Informiere dich jetzt.
Hilf uns, noch besser zu werden.
Wir sind immer auf der Suche nach neuen Talenten. Auch für dich ist die passende Stelle dabei.
Blog author
Sascha Masanneck
Do you still have questions? Just send me a message.
Do you still have questions? Just send me a message.