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
·
Ship Features Fearlessly
Turn features on and off without deploys. Used by thousands of Ruby developers.
→
Jamie McDonald
June 18, 2015
Programming
10
690
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
370
Android Engineering for Scale
jdamcd
13
2.2k
Other Decks in Programming
See All in Programming
AIによる高速開発をどう制御するか? ガードレール設置で開発速度と品質を両立させたチームの事例
tonkotsuboy_com
7
2.5k
AI & Enginnering
codelynx
0
140
CSC307 Lecture 09
javiergs
PRO
1
850
Python’s True Superpower
hynek
0
190
Geminiの機能を調べ尽くしてみた
naruyoshimi
0
170
今から始めるClaude Code超入門
448jp
8
9.5k
CSC307 Lecture 11
javiergs
PRO
0
580
受け入れテスト駆動開発(ATDD)×AI駆動開発 AI時代のATDDの取り組み方を考える
kztakasaki
2
430
AI時代でも変わらない技術コミュニティの力~10年続く“ゆるい”つながりが生み出す価値
n_takehata
2
440
CSC307 Lecture 08
javiergs
PRO
0
690
Raku Raku Notion 20260128
hareyakayuruyaka
0
420
izumin5210のプロポーザルのネタ探し #tskaigi_msup
izumin5210
1
440
Featured
See All Featured
The SEO Collaboration Effect
kristinabergwall1
0
370
From π to Pie charts
rasagy
0
140
More Than Pixels: Becoming A User Experience Designer
marktimemedia
3
340
A brief & incomplete history of UX Design for the World Wide Web: 1989–2019
jct
1
310
A Tale of Four Properties
chriscoyier
162
24k
Designing Powerful Visuals for Engaging Learning
tmiket
0
250
Documentation Writing (for coders)
carmenintech
77
5.3k
Organizational Design Perspectives: An Ontology of Organizational Design Elements
kimpetersen
PRO
1
620
Evolution of real-time – Irina Nazarova, EuRuKo, 2024
irinanazarova
9
1.2k
Save Time (by Creating Custom Rails Generators)
garrettdimon
PRO
32
2.3k
Reflections from 52 weeks, 52 projects
jeffersonlam
356
21k
Code Reviewing Like a Champion
maltzj
527
40k
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!