Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
Androidアプリ開発からみた RxJavaの使いどころ
Search
Naoki Morioka
May 16, 2017
Technology
4.1k
1
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Androidアプリ開発からみた RxJavaの使いどころ
JJUG CCC 2017 Spring #ccc_i3
Naoki Morioka
May 16, 2017
More Decks by Naoki Morioka
See All by Naoki Morioka
10年運用している 画像サービスでのJavaの活用と 今後の展望
nmorioka
0
630
モバイルアプリでHTTP/2
nmorioka
1
140
既存AndroidアプリでKotlin導入を考える
nmorioka
0
130
Cardbord SDK
nmorioka
0
110
AndroidでJava8
nmorioka
0
330
Other Decks in Technology
See All in Technology
More Freedom on the Same Shared GPU Cluster: A Small Team’s Experience with vCluster
nttcom
0
140
Meet AgentCore Identity Consent Portal
hironobuiga
3
190
FinTech 1-2 : Overview of FinTech
ks91
PRO
0
150
スキルを作る、その前に!複数人で使われるスキルを 作るためのプロセス
junkifurukawa
2
350
3つのアプローチで目指す チームを強くするAI駆動開発
thkt
0
120
予測不能な実行エージェントを安全にサクッと試せるサンドボックス環境の話
sansantech
PRO
0
130
ファミコンでPHPを動かす / PHP on the Famicom side b
tomzoh
0
140
AI Made Us Faster at Solving the Wrong Problems
marceloancelmo
0
180
私の推しは「聞いてから進む」AIです -AI-DLCに一人でアプリを作らせた話
yama3133
1
180
Snowflake Horizon Catalog と Apache Iceberg で作る オープンなデータ基盤
kitagawaz
0
450
Oracle Base Database Service 技術詳細
oracle4engineer
PRO
17
120k
AI 時代の Azure エンジニアリング ~ 私たちは何を磨き、何を任せるのか ~
chack411
1
530
Featured
See All Featured
Agile Leadership in an Agile Organization
kimpetersen
PRO
0
270
Have SEOs Ruined the Internet? - User Awareness of SEO in 2025
akashhashmi
0
510
The Hidden Cost of Media on the Web [PixelPalooza 2025]
tammyeverts
2
510
JAMstack: Web Apps at Ludicrous Speed - All Things Open 2022
reverentgeek
1
620
I Don’t Have Time: Getting Over the Fear to Launch Your Podcast
jcasabona
35
2.9k
jQuery: Nuts, Bolts and Bling
dougneiner
66
8.6k
Conquering PDFs: document understanding beyond plain text
inesmontani
PRO
4
3.2k
Leading Effective Engineering Teams in the AI Era
addyosmani
9
2.7k
Building Better People: How to give real-time feedback that sticks.
wjessup
370
20k
The Limits of Empathy - UXLibs8
cassininazir
2
710
Docker and Python
trallard
47
4.2k
Scaling GitHub
holman
464
140k
Transcript
"OESPJEΞϓϦ։ൃ͔ΒΈͨ 3Y+BWBͷ͍Ͳ͜Ζ ++6($$$4QSJOH /BPLJ.PSJPLB
ΤϯδχΞྺ $ݴޠΛ΄Ͳɺޙ΄ͱΜͲ+BWB ࠷ۙ"OEPSJEJ04ΞϓϦ։ൃ Ԭঘه !O@NPSJPLB IUUQTHJUIVCDPNONPSJPLB "CPVU.F ϑϦϡʔגࣜձࣾۈژࡏॅ
ࢲͷ3Y+BWBͷϞνϕʔγϣϯ w ؔܕzతzͳॲཧͷѻ͍͕Մೳ খ͍͞ॲཧΛΈ߹Θͤͯେ͖ͳॲཧΛهड़͍ͯ͘͠ +BWBͰهड़ग़དྷͯ΄Ͳྑ͍όϥϯεײ֮ w ͬͯΈΔͱ৭ʑͱ৽͍͠ൃݟ͕͋Δ qBU.BQ[JQDPNCJOF-BUFTUͳͲͷར༻
ར༻͍ͯ͠Δόʔδϣϯ w +%,@ w 3Y+BWB w 4QSJOH#PPU#6*-%4/"14)05 w 3FBDUPSɿ#6*-%4/"14)05
ΞδΣϯμ w 3Y+BWBͷ֓ཁ w 3Y+BWBͷجຊ w "OESPJEΞϓϦͰͷར༻ʹ͍ͭͯ w αʔόαΠυͰͷར༻ʹ͍ͭͯ w
·ͱΊ
w +BWB7.্Ͱಈ࡞͢Δ؍ଌՄೳ 0CTFSWBCMF ͳ࣌ܥྻσʔλ Λ༻͍ͨɺඇಉظͳΠϕϯτϕʔεͷϓϩάϥϛϯά ϦΞΫςΟ ϒϓϩάϥϛϯά ΛՄೳʹ͢ΔϥΠϒϥϦ w +BWBҎ্Ͱར༻Մೳ
w ݱঢ়ͷϝΠϯ3Y+BWBܥ w 3Y+BWB3FBDUJWF&YUFOTJPOT 3FBDUJWF4USFBNT 8IBU`T3Y+BWBʁ
ϦΞΫςΟϒϓϩάϥϛϯάᶃ w ͋ΔσʔλετϦʔϜʹରͯ͠ ͍ͭ͘Δ͔Θ͔Βͳ͍ σʔ λʹԠతʹϓϩάϥϛϯάΛߦ͏͜ͱ σʔλ ࣌ܥྻʹԊͬͨྲྀΕετϦʔϜ σʔλ ʜ
ϦΞΫςΟϒϓϩάϥϛϯάᶄ w 3Y+BWBʹ͓͍ͯ+BWBΠϯελϯεͷ͕ͭͭσʔλ 4USFBN"1*ͱಉ͡ " # $ 4USJOHσʔλ " "
" # $ # # $ $ # $ " # $ " # $ -JTUσʔλ
ϦΞΫςΟϒϓϩάϥϛϯάᶅ w σʔλετϦʔϜͷੜɺมɺ߹Λߦ͏ w ετϦʔϜ͔ΒདྷΔσʔλΛड͚औͬͨॲཧ ߪಡ Λهࡌ͢Δ " # $
Πϕϯτ " " Πϕϯτ ʜ B C D B B 4USJOH ͂ TUP-PXFS$BTF ม 4ZTUFNPVUQSJOUMO ߪಡ B C D ʜ
w ϚΠΫϩιϑτࣾʹΑͬͯఏএ͞ΕͨɺෳࡶͳඇಉظॲཧΠϕ ϯτॲཧɺ͕࣌ؒؔ͢ΔॲཧͳͲΛهड़Ͱ͖Δ"1*܊ͷ༷ w /&5+4ͳͲ֤छ࣮͕͋Δ w େ͖͍༷ 3FBDUJWF&YUFOTJPOT 3Y IUUQTHJUIVCDPN3FBDUJWF&YUFOTJPOT
w ϊϯϒϩοΩϯάͳ#BDL1SFTTVSFΛ༻͍ͨඇಉظετϦʔϜॲཧͷ༷ w ͭͷΠϯλʔϑΣʔεఆٛͷఏڙ 1VCMJTIFS 4VCTDSJCFS 4VCTDSJQUJPO 1SPDFTTPS w 5FTU4VJUFͷఏڙ
5$, w খ͍༷͞ 3FBDUJWF4USFBNT
3FBDUJWF4USFBNTΠϯλʔϑΣʔε Publisher public void subscribe(Subscriber<? super T> s); Subscriber public
void onSubscribe(Subscription s); public void onNext(T t); public void onError(Throwable t); public void onComplete(); /EBUBSFRVFTU /EBUBTUSFBNJOH TVCTDSJCF Subscription public void request(long n); public void cancel(); 1VCMJTIFS͕σʔλΛྲྀ͠4VCTDSJCFS͕σʔλΛड͚औΔॲཧ͕جຊ Processor public interface Processor<T, R> extends Subscriber<T>, Publisher<R> { }
#BDL1SFTTVSF w ड৴ଆ͔Βૹ৴ଆͷσʔλϑϩʔ੍ޚ w ॲཧ͕ऴΘͬͨ͜ͱΛ͑ͯ࣍ͷσʔλΛऔಘ͢Δ w ૹ৴ଆͷσʔλੜͷํ͕͍߹4USBUFHZʹैͬͨॲཧ࣮ࢪ w ࿈݁߹Մೳ ॲཧ͖ͬͨ͠ͷͰ࣍Լ͍͞
data 0, #BDL1SFTTVSF 4USBUFHZ #6''&3 %301 -"5&45 &3303 /0/& Publisher Subscriber
ΞδΣϯμ w 3Y+BWBͷ֓ཁ w 3Y+BWBͷجຊ w "OESPJEΞϓϦͰͷར༻ʹ͍ͭͯ w αʔόαΠυͰͷར༻ʹ͍ͭͯ w
·ͱΊ
3Y+BWBͷίΞ 'MPXBCMF0CTFSWBCMF
'MPXBCMF0CTFSWBCMFͱԿ͔ʁ w σʔλͷετϦʔϜΛੜ࢈ͯ͠ɺอ࣋͢ΔೖΕͷΑ͏ͳͷɻ ߪಡ TVCTDSJCF Մೳ 'MPXBCMF1VCMJTIFSΛ࣮ɺ#BDL1SFTTVSF੍ޚ͋Γɹ 0CTFSWBCMF#BDL1SFTTVSF੍ޚͳ͠ɻύϑΥʔϚϯεྑ͍ w ͭͷঢ়ଶΛߪಡऀʹ͑Δɹ
4VCTDSJCF/FYU$PNQMFUF&SSPS w ͭͷੑ࣭Λ࣋ͭ )PU $PME
̐ͭͷঢ়ଶ w 4VCTDSJCF௨ͷ४උ͕ग़དྷͨঢ়ଶ w /FYUσʔλ͕ྲྀΕ͍ͯΔঢ়ଶɻσʔλ༰͕ϋϯυϦϯά͞ΕΔ w $PNQMFUFਖ਼ৗऴྃɻετϦʔϜʹσʔλ͕ྲྀΕͳ͘ͳΔ w &SSPSҟৗऴྃɻετϦʔϜʹσʔλྲྀΕͳ͘ͳΔ OFYU
OFYU OFYU OFYU OFYU DPNQMFUF OFYU OFYU FSSPS TVCTDSJCF TVCTDSJCF
ߪಡॲཧ Flowable.just("1", "2", "3", "4") .subscribe(new Subscriber<String>() { public void
onSubscribe(Subscription subscription) { subscription.request(Long.MAX_VALUE); System.out.println("subscribed"); } public void onNext(String s) { int num = Integer.parseInt(s); System.out.println(num); } public void onError(Throwable throwable) { System.out.println("error"); } public void onComplete() { System.out.println("completed"); } }); TVCTDSJCFE DPNQMFUFE SFTVMU ੜ ᶃ։࢝ ᶄσʔλऔಘ ᶅਖ਼ৗऴྃ
ߪಡॲཧ ؔܕ*OUFSGBDF +BWB Flowable.just("1", "2", "3", "4") .subscribe(s -> {
int num = Integer.parseInt(s); System.out.println(num); }, throwable -> { System.out.println("error : " + throwable.getMessage()); }); SFTVMU /FYUॲཧϋϯυϦϯά Τϥʔॲཧ
ߪಡॲཧ ؔܕ*OUFSGBDF +BWB public final Disposable subscribe(Consumer<? super T> onNext,
Consumer<? super Throwable> onError, Action onComplete, Consumer<? super Subscription> onSubscribe) { LambdaSubscriber<T> ls = new LambdaSubscriber( onNext, onError, onComplete, onSubscribe); this.subscribe((FlowableSubscriber)ls); return ls; } ෦తʹ4VCTDSJCFSΛ࡞ͯ͠ॲཧ͍ͯ͠Δ
'MPXBCMFͱ+BWB4USFBN"1*ͱͷҧ͍ w 'MPXBCMF࠶ར༻Մೳ w 'MPXBCMF࣮ߦ5ISFBEΛॲཧ్தͰΓସ͑Մೳ w ྫ֎ͷѻ͍ 4USFBN"1*֎ଆʹൖ͢Δ 'MPXBCMF෦Ͱॲཧ͢Δ͜ͱ͕Մೳ
4USFBN"1* ࠶ར༻ෆՄ Stream<String> st = Arrays.asList("1", "2", "3", "4").stream(); st.forEach(s
-> { System.out.println(s); }); System.out.println(“next"); st.forEach(s -> { System.out.println(s); }); OFYU KBWBMBOH*MMFHBM4UBUF&YDFQUJPOTUSFBNIBTBMSFBEZCFFOPQFSBUFEVQPOPSDMPTFE BUKBWBVUJMTUSFBN"CTUSBDU1JQFMJOFJOJU "CTUSBDU1JQFMJOFKBWB ʜ SFTVMU
'MPXBCMF ࠶ར༻Մೳ Flowable<String> flowable = Flowable.just("1", "2", "3", "4"); flowable.subscribe(s
-> { System.out.println(s); }); System.out.println("next"); flowable.subscribe(s -> { System.out.println(s); }); OFYU SFTVMU
'MPXBCMF ྫ֎ͷѻ͍ Flowable.just("1", "2", "three", “4") .map(Integer::parseInt) .subscribe(num -> {
System.out.println(num); } , throwable -> { System.out.println("error : " + throwable.getMessage()); }); FSSPS'PSJOQVUTUSJOHUISFF SFTVMU /VNCFS'PSNBU&YDFQUJPO Τϥʔऴྃ
'MPXBCMF ࣮ߦ5ISFBE੍ޚ Flowable.just("a", "b", "c", "d") .map(s -> { System.out.println(Thread.currentThread().getName()
+ " : " + s); return s.toUpperCase(); }) .subscribeOn(Schedulers.newThread()) .observeOn(Schedulers.computation()) .blockingSubscribe(s -> { System.out.println(Thread.currentThread().getName() + " : " + s); }); 3Y/FX5ISFBE4DIFEVMFSB 3Y/FX5ISFBE4DIFEVMFSC 3Y/FX5ISFBE4DIFEVMFSD 3Y/FX5ISFBE4DIFEVMFSE 3Y$PNQVUBUJPO5ISFBE1PPM" 3Y$PNQVUBUJPO5ISFBE1PPM# 3Y$PNQVUBUJPO5ISFBE1PPM$ 3Y$PNQVUBUJPO5ISFBE1PPM% SFTVMU TVCTDSJCF0O'MPXBCMF0CTFSWFCMFॲཧͷ࣮ߦεϨου PCTFSWF0OͦΕҎ߱ͷ࣮ߦεϨου ݩͷ'MPXBCMFͷ࣮ߦεϨουΛࢦఆ ͜͜Ҏ߱ͷ࣮ߦεϨουΛࢦఆ
มॲཧ NBQ Flowable.just(1, 2, 3, 4) .map(num -> num *
num) .subscribe(num -> { System.out.println(num); }); SFTVMU NBQετϦʔϜͷσʔλͦͷͷΛม͢Δ
มॲཧ qBU.BQ Flowable.just(1, 2) .flatMap(v -> { // new flowable
return Flowable.just(v, 2 * v); }) .subscribe(System.out::println); SFTVMU qBU.BQσʔλ͔Β'MPXBCMFΛ࡞ͯ͠ ࠷ऴతʹl'MPXBCMFΛऔΓͬͯzετϦʔϜΛߏங͢Δ " 'MPXBCMF " " # $ 'MPXBCMF # # 'MPXBCMF $ $ " # $ " # $
มॲཧ qBU.BQ public Flowable<Integer> square(int v) { return Flowable.just(v).map(w ->
w * w); } public Flowable<Integer> twin(int v) { return Flowable.just(v, v); }; Flowable<Integer> f1 = Flowable.just(1,2); Flowable<Integer> f2 = f1.flatMap(v -> square(v)); Flowable<Integer> f3 = f2.flatMap(v -> twin(v)); f1.subscribe(v1 -> System.out.println("f1 : " + v1)); f2.subscribe(v1 -> System.out.println("f2 : " + v1)); f3.subscribe(v1 -> System.out.println("f3 : " + v1)); G G G G G G G G SFTVMU 'MPXBCMFʮ͋Δঢ়ଶʯͷσʔλετ ϦʔϜΛఆٛ͠ มͷΑ͏ʹѻ͑Δ
w ετϦʔϜͷੜॲཧ KVTUGSPN$BMMBCMFGSPN"SSBZͳͲ w σʔλมॲཧ pMUFSNBQqBU.BQͳͲ w ߹ॲཧ NFSHF[JQDPNCJOF-BUFTUͳͲ w
෭࡞༻ ߪಡऀͷ௨ͱผͷॲཧ EP0O4VCTDSJCFEP0O/FYUEP0O$PNQMFUFͳͲ ΦϖϨʔλͷछผ ม ੜ TVCTDSJCF ߹ ෭࡞༻ ੜ ม
)PU$PME
)PU$PMEͱ͍͏ੑ࣭ w ੜ࢈ऀ 'MPXBCMF0CTFSWBCMF ͷੑ࣭ w $PMEճ͝ͱͷར༻ ߪಡ͞Εͳ͍ͱՔಇͤͣɺߪಡ͝ͱʹ৽͍͠ετϦʔϜ͕࠶ੜ͞ΕΔ 'MPXBCMF0CTFSWBCMFେମ$PME ಈըͰݴ͏ͱ:PV5VCFͷ࠶ੜͷΑ͏ͳײ͡
w )PUܧଓతͳར༻ ετϦʔϜ͔ΒΛৗʹਨΕྲྀ͢ ෳͷߪಡऀʹಉ࣌ʹσʔλΛ௨͢Δ ಈըͰݴ͏ͱςϨϏͷΑ͏ͳײ͡
3Y+BWBͷ)PU$PME OFYU OFYU OFYU $PME 4VCTDSJCFS OFYU OFYU OFYU $PMEͷετϦʔϜߪಡऀ͝ͱʹ࠶࠶ੜ͞ΕΔΑ͏ͳΠϝʔδ
4VCTDSJCFS
3Y+BWBͷ)PU$PME OFYU OFYU OFYU )PU )PUͷߪಡߪಡऀ͕ਨΕྲྀ͞ΕΔσʔλΛͦΕͧΕಡΉΠϝʔδ ਨΕྲྀ͠ 4VCTDSJCFS 4VCTDSJCFS
)PUͳੜ࢈ऀ 1SPDFTTPS PublishProcessor<Integer> processor = PublishProcessor.create(); processor.subscribe(num -> { System.out.println("number1
: " + num); }); processor.subscribe(num -> { System.out.println("number2 : " + num); }); processor.onNext(1); processor.onNext(2); processor.onNext(3); processor.onNext(4); OVNCFS OVNCFS OVNCFS OVNCFS OVNCFS OVNCFS OVNCFS OVNCFS SFTVMU ߪಡొ ෳొՄೳ σʔλొ 1SPDFTTPSʹड͚ޱ༻ҙ͞Ε͍ͯΔ
ΞδΣϯμ w 3Y+BWBͷ֓ཁ w 3Y+BWBͷجຊ w "OESPJEΞϓϦͰͷར༻ʹ͍ͭͯ w αʔόαΠυͰͷར༻ʹ͍ͭͯ w
·ͱΊ
ϢʔβʔΞΫγϣϯͰͷ׆༻ྫ RxTextView.textChanges(a1Text) .subscribe(e -> { b1Text.setText( “” + (Long.parseLong(e.text) +
Long.parseLong(a2Text.getText()))); }); RxView.clicks(button) .debounce(1L, TimeUnit.SECONDS) .subscribe(x -> { // ੍ݶ͞Εͨೖྗ }) 3Y+BWBͷαϯϓϧͱͯ͠ग़ͯདྷΔ͕ ඞਢͱ͍͏Θ͚Ͱͳ͍ ݸਓతҙݟ
"OESPJEͰ3Y+BWB͕ ࠷ΘΕ͍Δ໘ ωοτϫʔΫ௨৴
લఏͱͯ͠"OESPJEΞϓϦͷ੍ݶ w ϘλϯλοϓͰը໘ΛϩοΫ͠ͳ͍͜ͱ͕ਪ͞ΕΔ w ը໘ૢ࡞6*εϨου ϝΠϯεϨου ͰͷΈ࣮ࢪՄೳ w ωοτϫʔΫ௨৴6*εϨουʮҎ֎ʯͰ࣮ࢪՄೳ 6*5ISFBE
*05ISFBE 7JFXߋ৽ "1*$BMM
ඪ४ͷ"TZOD5BTL-PBEFSαϯϓϧ public class MainActivity extends AppCompatActivity implements LoaderManager.LoaderCallbacks<Bitmap> { //
ActivityͷͲ͔͜ʹ͋ΔϘλϯλοϓίʔυ button.setOnClickListener(new OnSingleClickListener() { @Override public void onSingleClick(View view) { Bundle args = new Bundle(); args.putString("url", url); // ඇಉظॲཧΛґཔ getSupportLoaderManager().initLoader(0, args, this); } }); @Override public void Loader<Bitmap> onCreateLoader(int id, Bundle args) { return new ImageAsyncTaskLoader(this, args.getString("url")); } @Override public void onLoadFinished(Loader<Bitmap> arg0, Bitmap arg1) { imageView.setImageDrawable(new BitmapDrawable(getResources(), bmp)); } } Ϋϥογϡ͢ΔՄೳੑ͋Γ σʔλऔಘґཔ ݁Ռ$BMMCBDLΛड͚ͯ7JFXߋ৽
"TZOD5BTLதʹ"DUJWJUZ͕ফ͑ڈΔ w ωοτϫʔΫ௨৴தʹผͷը໘͕ىಈ͢Δ - ϝϞϦ͕গͳ͍ͱόοΫάϥϯυͷActivitykill͞ΕΔ w ωοτϫʔΫ௨৴தʹը໘͕ճస͞ΕΔ - ը໘͕ճస͞ΕΔͱActivity࠶࡞͞ΕΔ w
جຊతʹʮফ͑Δ͜ͱલఏʹ࡞Δʯͱ͍͏ελϯε
"OESPJEΞϓϦͷωοτϫʔΫ௨৴ w - AsyncTaskॲཧͰਖ਼࣮͘͢͠Δίετ͕ߴ͍ - Callback੍ޚ͕ෳࡶʹͳΓ1 ActivityͰ͑ΔAPIΛ૿͠ʹ͍͘ • ཧతͳॲཧ
- ࣮ߦεϨουͷ੍ޚΛ؆୯ʹߦ͍͍ͨ - Activityͷഁغ࣌ʹߋ৽ॲཧΛࢭΊ͍ͨ - ෳͷAPIΛݺͼग़͢߹ʹ͏·͘ॲཧ͍ͨ͠
3Y+BWB 3Y"OESPJE 3Y-JGFDZDMF
3Y+BWBͰ؆ܿʹهࡌ public class MainActivity extends RxActivity { // ActivityͷͲ͔͜ʹ͋ΔϘλϯλοϓίʔυ button.setOnClickListener(()
-> { Flowable.fromCallable(() -> { return userModel.get(userId); }) .compose(bindToLifecycle()) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(user -> { textView.setText(user.getName())); }); } } Ϣʔβʔใऔಘ "DUJWJUZ͕ഁغ͞ΕͨΒॲཧΛΊΔ 5ISFBE੍ޚ 7JFXߋ৽
࠶ར༻ͷͨΊʹ'MPXBCMFʹ͓͖͍ͯͨ͠ public class UserModel { public User get(String userId) {
… } } public class UserModel { public Flowable<User> get(String userId) { … } } 'MPXBCMFϕʔεͷΓΛ࡞
public class MainActivity extends RxActivity { button.setOnClickListener(() -> { userModel.get(userId)
.flatMap(user -> imageMode.loadBitmap(user.getProfileUrl)) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(bmp -> { imageView.setImageDrawable(new BitmapDrawable(getResources(), bmp)); }); } } ࠶ར༻ɿͭͷॲཧΛ߹ͯ݁͠ՌΛऔಘ ม࣌ʹՄಡੑ͕ߴ·Δ ϢʔβʔใΛऔಘͯ͠ ϓϩϑΟʔϧը૾औಘ
࠶ར༻ɿҰׅऔಘ [JQ public class MainActivity extends RxActivity { button.setOnClickListener(() ->
{ Flowable.zip( userModel.get(userId), imageModel.get(url) ) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe((user, bmp) -> { textView.setText(user.name); imageView.setImageDrawable(new BitmapDrawable(getResources(), bmp)); }); } } ෳͷॲཧΛҰؾʹཁٻͯ͠ ݁Ռ͕ͦΖͬͨஈ֊Ͱ7JFXߋ৽
ϦτϥΠ public class MainActivity extends RxActivity { button.setOnClickListener(() -> {
userModel.get(userId) .flatMap(user -> imageMode.loadBitmap(this.user.profileUrl)) .retry(3, throwable -> { // retryՄ൱ίʔυ return true; }) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(bmp -> { imageView.setImageDrawable(new BitmapDrawable(getResources(), bmp)); }); } } qBU.BQͨ͠ॲཧશମ͕Τϥʔ࣌࠶࣮ߦ͞ΕΔ
3Y+BWB ෳͷը໘ͷҰׅߋ৽ʹΘΕΔ
ಉҰσʔλΛࢀর͢Δෳͷը໘ w ϝϞϦ͕͋Ε"DUJWJUZ͕ελοΫ͞Ε͍͍ͯͯͬͯΔ w ΠϯελάϥϜͷz͍͍ͶzͳͲɺλοϓ͞Εͨॠؒʹશը ໘ʹσʔλΛөͤ͞Δඞཁ͕͋Δ IUUQTTIPNBEBOFUXQDPOUFOUVQMPBETTJOHMF5BTLYKQH
1SPDFTTPSΛར༻ͨ͠ߋ৽Πϕϯτϋϒ w 1SPDFTTPSʹྲྀΕΔσʔλΛߪಡ͢Δ͜ͱͰෳͷ7JFXΛ ߋ৽ग़དྷΔ 1SPDFTTPS 7JFXߋ৽ 7JFXߋ৽ %BUB $IBOHF &WFOU
PO/FYU TVCTDSJCF TVCTDSJCF
w ͭલʹྲྀΕͨσʔλΛอ࣋͢Δ#FIBWJPS1SPDFTTPS w ྫ͑࠷৽ͷϩάΠϯϢʔβʔσʔλΛΩϟογϡ͓ͯ͘͠ ͳͲͷ͍ํ͕ग़དྷΔ #FIBWJPS 1SPDFTTPS ৽ن7JFX 7JFXߋ৽ TVCTDSJCF
TVCTDSJCF ࠷৽ͷ݅Λอ࣋ %BUB $IBOHF &WFOU PO/FYU ৽͘͠TVCTDSJCF͞ΕͨͷʹΩϟογϡ͞Εͨ݅Λྲྀ͢ ༷ʑͳ1SPDFTTPS
w "OESPJEಛ༗ͷʹΑΓωοτϫʔΫ௨৴Ͱඞཁ 3Y+BWBΛߴͳ1SPNJTFతʹར༻ w .PEFMͷΓΛ'MPXBCMFԽ খ͞ͳॲཧΛ߹༷ͯ͠ʑͳॲཧΛੜΈग़͢ มߋͷଟ͍ϞόΠϧΞϓϦͰॏๅ͢Δ "OESPJEΞϓϦ։ൃͰͷ͔͍ͭͲ͜Ζ
ΞδΣϯμ w 3Y+BWBͷ֓ཁ w 3Y+BWBͷجຊ w "OESPJEΞϓϦͰͷར༻ʹ͍ͭͯ w αʔόαΠυͰͷར༻ʹ͍ͭͯ w
·ͱΊ
αʔόαΠυͰͷར༻Ҋ w ϚΠΫϩαʔϏεͰͷ"1*$BMM - ࣮ߦεϨου੍ޚ - Back PressureʹΑΔ੍ޚ - ෳαʔϏεݺͼग़͠ͷ߹
- ϦτϥΠͳͲͷ੍ޚ ϑϩϯτ͚"1* ϢʔβʔใαʔϏε ը૾ใαʔϏε "1*$BMM "1*$BMM "1*$BMM ҐஔใαʔϏε
3FBDUJWF8FC1SPHSBNNJOH
w Ϟσϧͷॲཧ %#ΞΫηεɺ"1*$BMM ΛετϦʔϜԽ w ίϯτϩʔϥͰϨεϙϯεΛੜ͢Δ࣌ʹϒϩοΩϯά͞ ΕΔ Ϟσϧ͚ͩϦΞΫςΟϒରԠʁ $POUSPMMFS ετϦʔϜ࡞
CMPDLJOH4VCTDSJCF .PEFM CMPDLJOH SFRVFTU SFTQPOTF
w ίϯτϩʔϥͰετϦʔϜΛߪಡ͠ͳ͍ͷͰϊϯϒϩοΩϯάͰॲཧՄೳ - ߴύϑΥʔϚϯε͕ظͰ͖Δ - εϨουͷ༗ޮར༻͕ظͰ͖Δ w )551ΫΤετͷड͚ޱʹ֤ͯσʔλͷੜग़ྗ·ͰͷzྲྀΕzΛ؆ܿʹ هड़ग़དྷΔ ίϯτϩʔϥͷϦΞΫςΟϒରԠ
$POUSPMMFS ετϦʔϜ࡞ TVCTDSJCF .PEFM 'SBNFXPSL ετϦʔϜ࡞ ετϦʔϜ ߹ɾม
4QSJOH#PPUͰ࣮ݱՄೳ
4QSJOHͰ3FBDUPS͕ΘΕΔ w 3YʹӨڹΛड͚ͨϦΞΫςΟϒϥΠϒϥϦ 3Y+BWBͱಉ͡ΦϖϨʔλଟ͋Γ w 3FBDUJWF4USFBNTʹ४ڌ 3Y+BWB 3FBDUPS ରԠ+BWBόʔδϣϯ +BWB
+BWB 0CTFSWBCMFγʔέϯε 'MPXBCMF 'MVY εϨου੍ޚϝιου TVCTDSJCF0O PCTFSWF0O TVCTDSJCF0O QVCMJTI0O 3Y+BWBͱ3FBDUPSͰେ͖͘ҧ͏ͱ͜Ζ
4QSJOH8FC3FBDUJWFͷαϯϓϧ @GetMapping(value = "/github_user", produces = "application/json") public Flux<GithubUser> githubUser()
{ return httpGet("https://api.github.com/users?slice=1") .flatMapMany(response -> response.bodyToFlux(GithubUser.class)) .take(5); } public Mono<ClientResponse> httpGet(String url) { WebClient client = WebClient.create(url); return client.get().uri("").exchange(); } public class GithubUser { public String login; public String avatar_url; public String toString() { return "[login : " + login + ", avator_url : " + avatar_url + "]"; } } > curl http://localhost/github_user [{"login":"mojombo","avatar_url":"https://avatars3.githubusercontent.com/u/1?v=3"}, {"login":"defunkt","avatar_url":"https://avatars3.githubusercontent.com/u/2?v=3"}, {"login":"pjhyett","avatar_url":"https://avatars3.githubusercontent.com/u/3?v=3"}, {"login":"wycats","avatar_url":"https://avatars3.githubusercontent.com/u/4?v=3"}, {"login":"ezmobius","avatar_url":"https://avatars3.githubusercontent.com/u/5?v=3"}] SFTVMU 'MVYϕʔεͷϨεϙϯε 3FBDUJWF8FC$MJFOU
͔ͨ͠͠Βศརͳ͍ํ w σʔλ৴੍ޚ - σʔλΛอ࣋͢ΔετϦʔϜ - λΠϛϯάΛ੍ޚ͢ΔΞΫγϣϯετϦʔϜ - 2ͭΛ͚ͯετϦʔϜԽͯ͠߹͢Δ͜ͱͰෳࡶͳ੍ޚΛ࣮ݱ σʔλετϦʔϜ
ΞΫγϣϯετϦʔϜ ఆظ࣮ߦඇಉظΠϕϯτ ߹ [JQ DPNCJOF-BUFTU σʔλ৴੍ޚ
[JQ w ̎ͭҎ্ ͭҎԼ ͷετϦʔϜΛʮ߹ʯ͢Δ w σʔλ͕ྲྀΕΔλΠϛϯά֤ετϦʔϜͷσʔλ͕ἧͬ ͨͱ͖ [JQ Y
Z lz Y Z " # $ " ߹݁Ռ # $
" # $ DPNCJOF-BUFTU w ̎ͭҎ্ ͭҎԼ ͷετϦʔϜΛʮ߹ʯ͢Δ w σʔλྲྀΕΔλΠϛϯάετϦʔϜͷͲΕ͔ʹz/FYUz͕ൃߦͨ͞ͱ͖
w /FYU͕ൃߦ͞Εͳ͔ͬͨํલճྲྀͨ͠σʔλ -BUFTU Λ࠶ྲྀ͢ DPNCJOF-BUFTU Y Z lz Y Z " ߹݁Ռ # # $ $
4FSWFS4FOU&WFOUTͰ߹Λ͏ @GetMapping(value = "/stream_data/", produces = "text/event-stream") public Flux<GithubUser> streamData()
{ Flux<Long> interval = Flux.interval(Duration.ofSeconds(1)); Flux<GithubUser> results = httpGet("https://api.github.com/users?slice=1") .flatMapMany(response -> response.bodyToFlux(GithubUser.class)) .take(5); return Flux.zip(interval, results) .map(Tuple2::getT2); } λΠϛϯάΛ͔Δ'MVY σʔλΛੜ͢Δ'MVY
[JQͨ݁͠Ռ ඵ͝ͱʹ̍ߦՃ͞Ε͍ͯ͘
ΞδΣϯμ w 3Y+BWBͷ֓ཁ w 3Y+BWBͷجຊ w "OESPJEΞϓϦͰͷར༻ w αʔόαΠυͰͷར༻ʹ͍ͭͯ w
·ͱΊ
࣮ࡍʹͲ͏ͬͯಋೖ͔ͨ͠ʁ w "OESPJEΞϓϦʹҎ্લʹಋೖ w J04։ൃऀͰϦΞΫςΟϒϓϩάϥϛϯά࣮ફऀ͕νʔϜʹ δϣΠϯͨ͠ͷ͕͖͔͚ͬ w ޱ಄ʹΑΔઆ໌13ϨϏϡʔΛ௨ͯ͡νʔϜʹൖ w ઃܭʹ͍ͭͯτϥΠΞϯυΤϥʔ
ҰੲલҰॹʹٞग़དྷΔਓ͕ډͳ͍ͱಋೖ͠ʹ͍͘ঢ়ଶͩͬͨ
ࠓͳΒಠशՄೳͰʁ w ʮ3Y+BWBϦΞΫςΟϒϓϩάϥϛϯάʯ͕ૉΒ͍͠ w ࣮ࡍʹखΛಈ͔༷ͯ͠ʑͳಈ࡞Λ֬ೝͯ͠ΈΔͷ͕ཧղͷۙಓ IUUQSYNBSCMFTDPNࢀߟʹ w ઃܭͳͲຊޠจݙ͕2JJUBʹͨ͘͞Μ্͕͍ͬͯΔ
3Y+BWBͰؾΛ͚ͭΔ͜ͱ w QVCMJDͳϝιουΛ'MPXBCMF0CTFSWBCMFʹґଘͤͨ͞ ߹ͷةݥੑ όʔδϣϯΞοϓ࣌ͷޙํޓੑͷةݥੑ ଞͷϑϨʔϜϫʔΫͷΓ͑ΒΕͳ͍ةݥੑ
$PODMVTJPO w 3Y+BWBඇಉظͳσʔλετϦʔϜΛॲཧ͢ΔϥΠϒϥϦɻεϨου੍ޚ͕ಛ తͰؔܕతͳΦϖϨʔλΛଟ࣋ͭ͘ w 3Y+BWBͷ͍ॴɿ"OESPJEΞϓϦͷͷωοτϫʔΫ௨৴ॲཧΛ؆ܿʹهड़ग़དྷ Δ w 8FCϓϩάϥϛϯάʹ͓͍ͯϦΞΫςΟϒϓϩάϥϛϯάॏཁΛ૿ͯ͠ ͖ͦ͏
w "OESPJEΞϓϦ։ൃҎ֎ͳΒ3FBDUPS͕ྑ͍બࢶͰ ͨͩ͠ຊޠจݙͷଟ͔͞Β3Y+BWBͰษڧ͓ͯ͘͠ͱ͍͏ͷΞϦͰ
ϦΞΫςΟϒϓϩάϥϛϯάͰ ͖ͬͱϓϩάϥϛϯά͕ ͬͱָ͘͠ͳΔͣʂ
ॕ"OESPJEͰ,PUMJO͕ਖ਼ࣜαϙʔτʂʂ w 3Y+BWB,PUMJOͰ͑Δ w 3Y,PUMJO͋Δ val list = listOf("Alpha", "Beta",
"Gamma", "Delta", "Epsilon") list.toObservable() // extension function for Iterables
ࢀߟจݙ w IUUQOJOKJOLVOIBUFOBCMPHDPNFOUSZJOUSPSYKB ʲ༁ʳ͋ͳ͕ͨٻΊ͍ͯͨϦΞΫςΟϒϓϩάϥϛϯάೖ w IUUQPLBQJFTIBUFCMPKQFOUSZ ؔܕϓϩάϥϚͷͨΊͷ3Yೖ w IUUQRJJUBDPNZVZB@QSFTUPJUFNTGBEEDGD 3Y+BWBʹͰೖ͠ɺ"OESPJEΞϓϦͷϦετૢ࡞ɺඇಉظॲཧɺมߋ௨ͷ՝Λղܾͨ͠
w IUUQTCMPHJLBNFOUSJFT 3Y+BWBϦΞΫςΟϒϓϩάϥϛϯάʯ4QSJOH3FBDUPSΛษڧ͢Δͷʹʹཱͭॻ੶ w IUUQTHJUIVCDPNKZVLVUZPTQSJOHSFBDUJWFFYBNQMF