Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Async Android
Search
Jamie McDonald
June 18, 2015
Programming
10
660
Async Android
NYC Android Developers Meetup, June 2015
Jamie McDonald
June 18, 2015
Tweet
Share
More Decks by Jamie McDonald
See All by Jamie McDonald
6 lessons learned scaling mobile
jdamcd
1
330
Android Engineering for Scale
jdamcd
13
2.1k
Other Decks in Programming
See All in Programming
『GO』アプリ バックエンドサーバのコスト削減
mot_techtalk
0
130
Writing documentation can be fun with plugin system
okuramasafumi
0
120
Honoのおもしろいミドルウェアをみてみよう
yusukebe
1
200
パスキーのすべて ── 導入・UX設計・実装の紹介 / 20250213 パスキー開発者の集い
kuralab
3
670
CloudNativePGがCNCF Sandboxプロジェクトになったぞ! 〜CloudNativePGの仕組みの紹介〜
nnaka2992
0
220
Kanzawa.rbのLT大会を支える技術の裏側を変更する Ruby on Rails + Litestream 編
muryoimpl
0
220
Ruby on cygwin 2025-02
fd0
0
140
DROBEの生成AI活用事例 with AWS
ippey
0
130
一休.com のログイン体験を支える技術 〜Web Components x Vue.js 活用事例と最適化について〜
atsumim
0
110
ASP. NET CoreにおけるWebAPIの最新情報
tomokusaba
0
360
CI改善もDatadogとともに
taumu
0
110
Java Webフレームワークの現状 / java web framework at burikaigi
kishida
9
2.2k
Featured
See All Featured
Refactoring Trust on Your Teams (GOTO; Chicago 2020)
rmw
33
2.8k
Chrome DevTools: State of the Union 2024 - Debugging React & Beyond
addyosmani
3
310
Code Reviewing Like a Champion
maltzj
521
39k
The Invisible Side of Design
smashingmag
299
50k
Reflections from 52 weeks, 52 projects
jeffersonlam
348
20k
I Don’t Have Time: Getting Over the Fear to Launch Your Podcast
jcasabona
31
2.1k
Why Our Code Smells
bkeepers
PRO
335
57k
Producing Creativity
orderedlist
PRO
343
39k
Distributed Sagas: A Protocol for Coordinating Microservices
caitiem20
330
21k
Art, The Web, and Tiny UX
lynnandtonic
298
20k
Imperfection Machines: The Place of Print at Facebook
scottboms
267
13k
Mobile First: as difficult as doing things right
swwweet
223
9.3k
Transcript
None
Async Android Jamie McDonald
@Override public void onCreate() { super.onCreate(); Log.i(TAG, “Hi from the
main thread!”); } Main Thread title, date, 01 of 10
ANR title, date, 01 of 10
ANR title, date, 01 of 10 I/Choreographer﹕ Skipped 480 frames!
The application may be doing too much work on its main thread.
@UiThread public void updateUi(String title) { textView.setText(title); } @WorkerThread public
void showTitle() { textView.setText(SlowStuff.loadTitle()); } Tools title, date, 01 of 10
@UiThread public void updateUi(String title) { textView.setText(title); } @WorkerThread public
void showTitle() { textView.setText(SlowStuff.loadTitle()); } Tools title, date, 01 of 10
new Thread() { public void run() { final String result
= SlowStuff.blocking(); new Handler().post(new Runnable() { @Override public void run() { updateUi(result); } }); } }.start(); Thread title, date, 01 of 10
class LooperThread extends Thread { private Handler handler; public void
run() { Looper.prepare(); handler = new Handler() { public void handleMessage(Message msg) { // Process messages here } }; Looper.loop(); } } Looper title, date, 01 of 10
IntentService title, date, 01 of 10 public class BackgroundService extends
IntentService { public BackgroundService() { super("BackgroundWork"); } @Override protected void onHandleIntent(Intent intent) { SlowStuff.blocking(); } } startService(new Intent(this, BackgroundService.class));
new AsyncTask<Void, Void, String>() { @Override protected String doInBackground(Void... params)
{ return SlowStuff.blocking(); } @Override protected void onPostExecute(String s) { updateUi(s); } }.execute(); AsyncTask title, date, 01 of 10
title, date, 01 of 10 “Painless threading” - The year
2009
new AsyncTask<Void, Void, Result>() { [...] @Override protected void onPostExecute(Result
result) { if (result.isSuccess()) { doNextAsyncStep(result.getValue()); } else { // ??? } } }.execute(); Callback Hell title, date, 01 of 10
Execution Order title, date, 01 of 10 SERIAL SERIAL THREAD
POOL
class DataLoader extends AsyncTaskLoader<String> { public BackgroundLoader(Context context) { super(context);
} @Override protected void onStartLoading() { forceLoad(); } @Override public String loadInBackground() { return SlowStuff.blocking(); } } Loader title, date, 01 of 10
getLoaderManager().initLoader(LOADER_ID, null, new LoaderManager.LoaderCallbacks<String>() { @Override public Loader<String> onCreateLoader(int id,
Bundle args) { return new DataLoader(MainActivity.this); } @Override public void onLoadFinished(Loader<String> loader, String text) { updateUi(text); } @Override public void onLoaderReset(Loader<String> loader) { loader.reset(); } }); Loader title, date, 01 of 10
Enter RxJava!
RxJava title, date, 01 of 10 “RxJava tries to be
very lightweight. [...] focused on just the Observable abstraction and related higher-order functions”
Observer Pattern title, date, 01 of 10
Streams title, date, 01 of 10
public Observable<String> observable() { return Observable.create((subscriber) -> { subscriber.onNext(blocking()); subscriber.onCompleted();
}); } Observable title, date, 01 of 10
class MySubscriber extends DefaultSubscriber<String> { @Override public void onNext(String text)
{ updateUi(text); } @Override public void onError(Throwable e) { displayError(e); } } Subscriber title, date, 01 of 10
SlowStuff.observable() .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(new MySubscriber()); Schedulers title, date, 01 of
10
title, date, 01 of 10 Thread IntentService AsyncTask Loader RxJava
Main thread callbacks Configuration changes Error handling Composability Flexible scheduling
Operators title, date, 01 of 10 flatMap map filter doOnNext
onErrorResumeNext distinct cache zip retry ...
FlatMap title, date, 01 of 10
trackOps.loadWaveformUrl(urn) .flatMap(url -> imageOps.renderWaveform(url)) .onErrorResumeNext(imageOps.defaultWaveform()) [...] .subscribe(new WaveformSubscriber()); FlatMap title,
date, 01 of 10
OnErrorResumeNext title, date, 01 of 10
public final class EventQueue { static final Queue<StateTransition> PLAYBACK_STATE; static
final Queue<ProgressEvent> PLAYBACK_PROGRESS; static final Queue<PlayableEvent> PLAYABLE_CHANGED; [...] } Event Bus title, date, 01 of 10
None
title, date, 01 of 10
Subtitle title, date, 01 of 10 eventBus.queue(EventQueue.PLAYABLE_CHANGE) .filter(PlayableEvent.IS_TRACK_FILTER) .doOnNext(updateLikeCount) .observeOn(AndroidSchedulers.mainThread())
Only listen to interesting events
Subtitle Respond to state without storing it title, date, 01
of 10 Observable.combineLatest( eventBus.queue(EventQueue.PLAY_QUEUE_TRACK), eventBus.queue(EventQueue.PLAYER_UI), combineStates) .doOnNext(setTrackHasBeenSeen)
Downsides title, date, 01 of 10 Debugging Testing long call
chains Learning curve Boilerplate Config changes Backpressure Where & when to use it?
*£#%@£$?? title, date, 01 of 10
More title, date, 01 of 10 RxAndroid Not RxAndroid Retrofit
Retrolambda
soundcloud.com/jobs Thank you, NYC!