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
Sponsored
·
Your Podcast. Everywhere. Effortlessly.
Share. Educate. Inspire. Entertain. You do you. We'll handle the rest.
→
Jamie McDonald
June 18, 2015
Programming
690
10
Share
Async Android
NYC Android Developers Meetup, June 2015
Jamie McDonald
June 18, 2015
More Decks by Jamie McDonald
See All by Jamie McDonald
6 lessons learned scaling mobile
jdamcd
1
380
Android Engineering for Scale
jdamcd
13
2.2k
Other Decks in Programming
See All in Programming
10年分の技術的負債、完済へ ― Claude Code主導のAI駆動開発でスポーツブルを丸ごとリプレイスした話
takuya_houshima
0
2.6k
Kingdom of the Machine
yui_knk
2
310
アーキテクチャモダナイゼーションとは何か
nwiizo
19
5.2k
飯MCP
yusukebe
0
510
JAWS-UG横浜 #100 祝・第100回スペシャルAWS は VPC レスの時代へ
maroon1st
0
140
10 Tips of AWS ~Gen AI on AWS~
licux
5
400
Going Multiplatform with Your Android App (Android Makers 2026)
zsmb
2
420
Oxlintとeslint-plugin-react-hooks 明日から始められそう?
t6adev
0
270
JOAI2026 1st solution - heron0519 -
heron0519
0
140
Liberating Ruby's Parser from Lexer Hacks
ydah
2
1.2k
ルールルルルルRubyの中身の予備知識 ── RubyKaigiの前に予習しなイカ?
ydah
1
180
UIの境界線をデザインする | React Tokyo #15 メイントーク
sasagar
2
360
Featured
See All Featured
Bioeconomy Workshop: Dr. Julius Ecuru, Opportunities for a Bioeconomy in West Africa
akademiya2063
PRO
1
94
コードの90%をAIが書く世界で何が待っているのか / What awaits us in a world where 90% of the code is written by AI
rkaga
61
43k
The Cost Of JavaScript in 2023
addyosmani
55
9.8k
A better future with KSS
kneath
240
18k
How STYLIGHT went responsive
nonsquared
100
6.1k
Being A Developer After 40
akosma
91
590k
Mobile First: as difficult as doing things right
swwweet
225
10k
Lessons Learnt from Crawling 1000+ Websites
charlesmeaden
PRO
1
1.2k
Navigating Team Friction
lara
192
16k
Game over? The fight for quality and originality in the time of robots
wayneb77
1
160
Stop Working from a Prison Cell
hatefulcrawdad
274
21k
Breaking role norms: Why Content Design is so much more than writing copy - Taylor Woolridge
uxyall
0
260
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!