modern android app library stack

64
Modern Android app library stack Tomáš Kypta #MobCon

Upload: tomas-kypta

Post on 06-Apr-2017

105 views

Category:

Technology


8 download

TRANSCRIPT

Page 1: Modern Android app library stack

Modern Android app library stackTomáš Kypta

#MobCon

Page 2: Modern Android app library stack

Getting into Android

Page 3: Modern Android app library stack

Q: “How do I get the data from the server?”

Page 4: Modern Android app library stack

A: “Use AsyncTask!”

The old school approach™

Page 5: Modern Android app library stack

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); } }}

Page 6: Modern Android app library stack

Old school Android apps

• business logic in activities

• with all the bad stuff such as networking

• and memory leaks

• and crashes

Page 7: Modern Android app library stack

Modern Android apps

• use cleaner architectures

• MVP, MVVM, MVI

• use libraries heavily

• use tests

Page 8: Modern Android app library stack

Libraries

• save time and work

• simplify API

• back-port new APIs to older Android version

Page 9: Modern Android app library stack

Ideal Android Library• “perform one task and perform it well”

• easy to use

• open-source

• easily available

• through a remote Maven repository

Page 10: Modern Android app library stack

Ideal Android Library

• doesn’t eat too much resources

• doesn’t require too many permissions

• behave nicely when crashing

Page 11: Modern Android app library stack

“I wan’t my app to work on Android from version 4.1.”

98% of Android devices!

Page 12: Modern Android app library stack

Support libraries

• available through Android SDK

• backport newer Android APIs

• helper classes

• debugging, testing, utilities

Page 13: Modern Android app library stack

Support libraries• AsyncTaskLoader

• com.android.support:support-core-utils:25.3.0

• ViewPager

• com.android.support:support-core-ui:25.3.0

• support fragments

• com.android.support:support-fragment:25.3.0

Page 14: Modern Android app library stack

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

Page 15: Modern Android app library stack

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

Page 16: Modern Android app library stack

Support libraries

• Having more than 64k methods?

• And supporting Android prior 5.0?

• com.android.support:multidex:1.0.1

Page 17: Modern Android app library stack

“This dependency injection thing sounds useful.”

Page 18: Modern Android app library stack

Dagger 2

• dependency injection framework for Android and Java

• avoids reflection

• uses compile-time generated code

Page 19: Modern Android app library stack

Dagger 2public class SimpleGameProvider {

private ApiProvider mApiProvider; private StorageProvider mStorageProvider;

@Inject public SimpleProvider(ApiProvider apiProvider, StorageProvider storageProvider) { mApiProvider = apiProvider; mStorageProvider = storageProvider; }

public void doSomething() { // … }}

Page 20: Modern Android app library stack

Dagger 2@Modulepublic class AppModule {

private Context mApplicationContext;

public AppModule(Context applicationContext) { mApplicationContext = applicationContext; }

@Singleton @Provides protected OtherProvider provideTheOther(Context context) { return new OtherProvider(context); }}

Page 21: Modern Android app library stack

Dagger 2

@Singleton@Component(modules = {AppModule.class})public interface AppComponent {

void inject(MainActivity activity);}

Page 22: Modern Android app library stack

Dagger 2public 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 }}

Page 23: Modern Android app library stack

“My server has this REST API…”

Page 24: Modern Android app library stack

Retrofit

• simple REST client for Android and Java

• annotation-based API

• type-safe

• Rx compatible

Page 25: Modern Android app library stack

Retrofitpublic 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);}

Page 26: Modern Android app library stack

RetrofitRestAdapter 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);

Page 27: Modern Android app library stack

“And my server has this fancy new features…”

Page 28: Modern Android app library stack

OkHttp• an efficient HTTP client for Android and Java

• requests can be easily customized

• support for HTTP/2

• connection pooling

• transparent GZIP

• response caching

Page 29: Modern Android app library stack

OkHttp

OkHttpClient client = new OkHttpClient();Request request = new Request.Builder() .url(url) .build();

Response response = client.newCall(request).execute();return response.body().string();

Page 30: Modern Android app library stack

OkHttp

• Works out of the box with the latest Retrofit!

Page 31: Modern Android app library stack

“The server returns 400. What’s wrong?”

Page 32: Modern Android app library stack

Stetho

• A debug bridge

• hooks into Chrome Developer Tools

Page 33: Modern Android app library stack

Stetho• network inspection

• database inspection

• view hierarchy

• dumpapp system allowing custom plugins

• command-line interface for communication with the plugins

Page 34: Modern Android app library stack
Page 35: Modern Android app library stack

Stetho

public class MyApplication extends Application {

@Override public void onCreate() { super.onCreate();

Stetho.initializeWithDefaults(this); }}

Page 36: Modern Android app library stack
Page 37: Modern Android app library stack

Stetho

OkHttpClient okHttpClient = new OkHttpClient.Builder() .addNetworkInterceptor(new StethoInterceptor()) .build();

Page 38: Modern Android app library stack

“Why I’m getting this OutOfMemoryError?”

Page 39: Modern Android app library stack

LeakCanary

• memory leak detection library

• notifies about memory leaks during app development

Page 40: Modern Android app library stack

LeakCanary

dependencies { debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5' releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5' testCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5' }

Page 41: Modern Android app library stack

“How to display this remote product image?”

Page 42: Modern Android app library stack

Image loaders

• tons of libs

• Universal Image Loader

• Picasso

• Glide

Page 43: Modern Android app library stack

Picasso

Picasso.with(context) .load(url) .resize(50, 50) .centerCrop() .placeholder(R.drawable.placeholder) .error(R.drawable.error) .into(vImageView);

Page 44: Modern Android app library stack

“How can I notify that class?“

“There has to be some way without refactoring the whole thing!”

Page 45: Modern Android app library stack

Event bus

• for communication between decoupled parts of an app

• EventBus

Page 46: Modern Android app library stack

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());

Page 47: Modern Android app library stack

“How do I get the data from the server?”

“And I have to combine couple of sources.”

Page 48: Modern Android app library stack

RxJava

• general Java library

• reactive programming

• push concept

• composable data flow

Page 49: Modern Android app library stack

RxJava

• useful for simple async processing

• async composition

• offers simple chaining of operations on data

• eliminates callback hell

Page 50: Modern Android app library stack

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

Page 51: Modern Android app library stack

RxJava data flowObservable .from(new String[]{"Hello", "Droidcon!"})

creation

Page 52: Modern Android app library stack

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

creation

Page 53: Modern Android app library stack

RxJava data flowObservable .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

Page 54: Modern Android app library stack

RxJava data flowObservable .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

Page 55: Modern Android app library stack

RxJava data flow with Java 8

creationtransformationsubscription

Observable .from(new String[]{"Hello", "Droidcon!"}) .map(s -> s.toUpperCase(Locale.getDefault())) .reduce((s,s2) -> s + ' ' + s2) .subscribe(s -> Timber.i(s));

Page 56: Modern Android app library stack

Other Rx libraries

RxAndroidRxBinding

RxLifecycle

RxNavi

SQLBrite

RxRelay

Page 57: Modern Android app library stack

“This new feature is great! I bet users will love it!”

Page 58: Modern Android app library stack

Analytics & crash reporting

• Google Analytics

• Crashlytics

• Firebase

Page 59: Modern Android app library stack

“I don’t like this Java language.”

Page 60: Modern Android app library stack

Kotlin

• not a library

• a JVM programming language

• “Swift for Android devs"

Page 61: Modern Android app library stack

Q: “So all I have to do is to Google for a library to do the thing?”

Page 62: Modern Android app library stack

A: “think wisely before adding a new library.”

Page 63: Modern Android app library stack

Final thoughts• many potential problems

• transitive dependencies

• permissions

• app size

• slow app start

• threads

• logs

Page 64: Modern Android app library stack

Questions?