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

Modern Android app library stack

Modern Android app library stack

The world of open source libraries and tools is vast for Android developers. Writing apps using solely Android SDK is impractical. Libraries can help you in many ways. They can speed up your development, save you creating boilerplate code and dealing with platform fragmentation, simplify your code and make it more readable and maintainable. In the talk I’m showing how several truly useful libraries can help a developer.
Presented at MobCon Europe 2017.

Tomáš Kypta

March 26, 2017
Tweet

More Decks by Tomáš Kypta

Other Decks in Programming

Transcript

  1. public class MainActivity extends Activity { @Override public void onCreate(Bundle

    savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Button btn = (Button) findViewById(R.id.btn); btn.setOnClickListener(new View.OnClickListener { public void onClick(View view) { new DownloadTask().execute(inputString); } }); } private class DownloadTask extends AsyncTask<String, Void, String> { @Override protected String doInBackground(String... params) { // download some data } @Override protected void onPostExecute(String result) { TextView txt = (TextView) findViewById(R.id.text); txt.setText(result); } } }
  2. Old school Android apps • business logic in activities •

    with all the bad stuff such as networking • and memory leaks • and crashes
  3. Modern Android apps • use cleaner architectures • MVP, MVVM,

    MVI • use libraries heavily • use tests
  4. Libraries • save time and work • simplify API •

    back-port new APIs to older Android version
  5. Ideal Android Library • “perform one task and perform it

    well” • easy to use • open-source • easily available • through a remote Maven repository
  6. Ideal Android Library • doesn’t eat too much resources •

    doesn’t require too many permissions • behave nicely when crashing
  7. “I wan’t my app to work on Android from version

    4.1.” 98% of Android devices!
  8. Support libraries • available through Android SDK • backport newer

    Android APIs • helper classes • debugging, testing, utilities
  9. Support libraries • AppCompatActivity, ActionBar • com.android.support:appcompat-v7:25.3.0 • RecyclerView •

    com.android.support:recyclerview-v7:25.3.0 • CardView • com.android.support:cardview-v7:25.3.0
  10. Support libraries • com.android.support:support-annotations:25.3.0 • useful annotations • StringRes, IntDef,

    Nullable, UiThread, WorkerThread, CallSuper, VisibleForTesting, … • com.android.support:design:25.3.0 • Material design
  11. Support libraries • Having more than 64k methods? • And

    supporting Android prior 5.0? • com.android.support:multidex:1.0.1
  12. Dagger 2 • dependency injection framework for Android and Java

    • avoids reflection • uses compile-time generated code
  13. Dagger 2 public class SimpleGameProvider { private ApiProvider mApiProvider; private

    StorageProvider mStorageProvider; @Inject public SimpleProvider(ApiProvider apiProvider, StorageProvider storageProvider) { mApiProvider = apiProvider; mStorageProvider = storageProvider; } public void doSomething() { // … } }
  14. Dagger 2 @Module public class AppModule { private Context mApplicationContext;

    public AppModule(Context applicationContext) { mApplicationContext = applicationContext; } @Singleton @Provides protected OtherProvider provideTheOther(Context context) { return new OtherProvider(context); } }
  15. Dagger 2 public class MainActivity extends AppCompatActivity { @Inject SimpleProvider

    mSimpleProvider; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); ((MyApplication) getApplication()).getAppComponent().inject(this); // and now we can use mSimpleProvider } }
  16. Retrofit • simple REST client for Android and Java •

    annotation-based API • type-safe • Rx compatible
  17. Retrofit public interface GitHubApi { @GET("/users/{username}") User getUser(@Path("username") String username);

    @GET("/users/{username}/repos") List<Repo> getUserRepos(@Path("username") String username); @POST("/orgs/{org}/repos") RepoCreationResponse createRepoInOrganization( @Path("org") String organization, @Body RepoCreationRequest request); }
  18. Retrofit RestAdapter adapter = new RestAdapter.Builder() .setEndpoint(GITHUB_API_URL) .setRequestInterceptor(new RequestInterceptor() {

    @Override public void intercept(RequestFacade request) { request.addHeader("Accept", "application/vnd.github.v3+json"); } }) .setLogLevel(RestAdapter.LogLevel.BASIC) .build(); GitHubApi gitHubApi = adapter.create(GitHubApi.class);
  19. OkHttp • an efficient HTTP client for Android and Java

    • requests can be easily customized • support for HTTP/2 • connection pooling • transparent GZIP • response caching
  20. OkHttp OkHttpClient client = new OkHttpClient(); Request request = new

    Request.Builder() .url(url) .build(); Response response = client.newCall(request).execute(); return response.body().string();
  21. Stetho • network inspection • database inspection • view hierarchy

    • dumpapp system allowing custom plugins • command-line interface for communication with the plugins
  22. Stetho public class MyApplication extends Application { @Override public void

    onCreate() { super.onCreate(); Stetho.initializeWithDefaults(this); } }
  23. “How can I notify that class?“ “There has to be

    some way without refactoring the whole thing!”
  24. EventBus • events • subscribers • register and unregister •

    post events public static class MessageEvent { /* fields if needed */ } @Subscribe(threadMode = ThreadMode.MAIN) public void onMessageEvent(MessageEvent event) {/* handle event */}; EventBus.getDefault().register(this); EventBus.getDefault().unregister(this); EventBus.getDefault().post(new MessageEvent());
  25. “How do I get the data from the server?” “And

    I have to combine couple of sources.”
  26. RxJava • useful for simple async processing • async composition

    • offers simple chaining of operations on data • eliminates callback hell
  27. RxJava • works well with Retrofit • can completely replace

    event bus libraries • hard to learn • RxJava 1 vs. RxJava 2 • they will coexist for some time
  28. RxJava data flow Observable .from(new String[]{"Hello", "Droidcon!"}) .map(new Func1<String, String>()

    { @Override public String call(String s) { return s.toUpperCase(Locale.getDefault()); } }) creation
  29. RxJava data flow Observable .from(new String[]{"Hello", "Droidcon!"}) .map(new Func1<String, String>()

    { @Override public String call(String s) { return s.toUpperCase(Locale.getDefault()); } }) .reduce(new Func2<String, String, String>() { @Override public String call(String s, String s2) { return s + ' ' + s2; } }) creation transformation
  30. RxJava data flow Observable .from(new String[]{"Hello", "Droidcon!"}) .map(new Func1<String, String>()

    { @Override public String call(String s) { return s.toUpperCase(Locale.getDefault()); } }) .reduce(new Func2<String, String, String>() { @Override public String call(String s, String s2) { return s + ' ' + s2; } }) .subscribe(new Action1<String>() { @Override public void call(String s) { Timber.i(s); } }); creation transformation subscription
  31. RxJava data flow with Java 8 creation transformation subscription Observable

    .from(new String[]{"Hello", "Droidcon!"}) .map(s -> s.toUpperCase(Locale.getDefault())) .reduce((s,s2) -> s + ' ' + s2) .subscribe(s -> Timber.i(s));
  32. Q: “So all I have to do is to Google

    for a library to do the thing?”
  33. Final thoughts • many potential problems • transitive dependencies •

    permissions • app size • slow app start • threads • logs