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
700
10
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
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
Copilot CLI の継戦能力を高める コンテキスト管理
nozomutu
1
1.2k
PHPで使える日時の表現と、その知り方 #frontend_phpcon_do
o0h
PRO
0
230
Swiftのレキシカルスコープ管理
kntkymt
0
220
Developing with AI Agents — Codex, Claude Code & Cowork Practical Guide
x5gtrn
PRO
0
1.3k
依存関係から依存物へ―Dependencyという言葉の歴史をひも解く
j_lee
0
110
スマートグラスで並列バイブコーディング
hyshu
0
120
AIで効率化できた業務・日常
ochtum
0
120
OSもどきOS
arkw
0
530
Skillsは効率化、Agentsは"自分の拡張"——Builder時代のエージェント編成(CC Night 2026)
wemra
1
120
Technical Debt: Understanding it Rightly, Engaging it Rightly #LaravelLiveJP
shogogg
0
220
フロントエンドとバックエンドで「1文字」を揃えよう
youkidearitai
PRO
0
260
Oxlintのカスタムルールの現況
syumai
6
1.1k
Featured
See All Featured
DevOps and Value Stream Thinking: Enabling flow, efficiency and business value
helenjbeal
1
230
Responsive Adventures: Dirty Tricks From The Dark Corners of Front-End
smashingmag
254
22k
Measuring Dark Social's Impact On Conversion and Attribution
stephenakadiri
2
220
Designing Powerful Visuals for Engaging Learning
tmiket
1
410
The Director’s Chair: Orchestrating AI for Truly Effective Learning
tmiket
1
190
Keith and Marios Guide to Fast Websites
keithpitt
413
23k
Un-Boring Meetings
codingconduct
0
310
Deep Space Network (abreviated)
tonyrice
0
170
Balancing Empowerment & Direction
lara
6
1.2k
Dealing with People You Can't Stand - Big Design 2015
cassininazir
367
27k
Sam Torres - BigQuery for SEOs
techseoconnect
PRO
0
280
Prompt Engineering for Job Search
mfonobong
0
340
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!