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
Sponsored
·
Ship Features Fearlessly
Turn features on and off without deploys. Used by thousands of Ruby developers.
→
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
320
Other Decks in Technology
See All in Technology
AI時代、データエンジニアが一番おもろい
genshun9
0
550
Reactの設計論
uhyo
22
12k
DEFCON_CHV_CTF_Write-up.pdf
bata_24
0
150
synctest時代のhttptest Go 1.27で変わるHTTPサーバテストの裏側 / go conference2026 synctest and httptest
budougumi0617
1
2.8k
TinyGo 開発サイクルを高速化する:Go で作るエミュレータ入門
zozotech
PRO
1
720
Claude in Chrome 入門 / Introduction to Claude in Chrome
cielo1985
0
740
Claude Codeを「使うほど育つ」AI秘書にするノウハウ
minorun365
PRO
13
7.9k
Omarchy Quattro の日本語設定周り
simosako
2
170
10Xに技術的負債をもたらした「2つの境界の歪み」その構造と解消への営み
10xinc
0
1.4k
例外の正しい扱い方 そのエラー try-catchして大丈夫?
jinwatanabe
3
500
空間オーディオで過去の 自分(ゴースト)と競うランニング 〜HealthKitのルートを足音に変える実装〜
nao_randd
0
170
安心して変更できるWebフロントエンドの作り方
pirosikick
4
2.2k
Featured
See All Featured
Intergalactic Javascript Robots from Outer Space
tanoku
273
27k
Why Mistakes Are the Best Teachers: Turning Failure into a Pathway for Growth
auna
0
280
Lightning Talk: Beautiful Slides for Beginners
inesmontani
PRO
2
690
Keith and Marios Guide to Fast Websites
keithpitt
413
23k
HU Berlin: Industrial-Strength Natural Language Processing with spaCy and Prodigy
inesmontani
PRO
0
700
Information Architects: The Missing Link in Design Systems
soysaucechin
1
1.1k
Ecommerce SEO: The Keys for Success Now & Beyond - #SERPConf2024
aleyda
1
2.1k
GraphQLの誤解/rethinking-graphql
sonatard
75
12k
技術選定の審美眼(2025年版) / Understanding the Spiral of Technologies 2025 edition
twada
PRO
120
120k
The Cult of Friendly URLs
andyhume
79
7k
Design and Strategy: How to Deal with People Who Don’t "Get" Design
morganepeng
133
19k
Navigating the Design Leadership Dip - Product Design Week Design Leaders+ Conference 2024
apolaine
2
430
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