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
Androidアプリ開発からみた RxJavaの使いどころ
Search
Naoki Morioka
May 16, 2017
Technology
1
3.8k
Androidアプリ開発からみた RxJavaの使いどころ
JJUG CCC 2017 Spring #ccc_i3
Naoki Morioka
May 16, 2017
Tweet
Share
More Decks by Naoki Morioka
See All by Naoki Morioka
10年運用している 画像サービスでのJavaの活用と 今後の展望
nmorioka
0
500
モバイルアプリでHTTP/2
nmorioka
1
120
既存AndroidアプリでKotlin導入を考える
nmorioka
0
94
Cardbord SDK
nmorioka
0
87
AndroidでJava8
nmorioka
0
280
Other Decks in Technology
See All in Technology
【技術書典17】OpenFOAM(自宅で極める流体解析)2次元円柱まわりの流れ
kamakiri1225
0
210
WINTICKETアプリで実現した高可用性と高速リリースを支えるエコシステム / winticket-eco-system
cyberagentdevelopers
PRO
1
190
グローバル展開を見据えたサービスにおける機械翻訳プラクティス / dp-ai-translating
cyberagentdevelopers
PRO
1
150
サイバーエージェントにおける生成AIのリスキリング施策の取り組み / cyber-ai-reskilling
cyberagentdevelopers
PRO
2
190
ExaDB-D dbaascli で出来ること
oracle4engineer
PRO
0
3.6k
Amazon FSx for NetApp ONTAPを利用するにあたっての要件整理と設計のポイント
non97
1
160
[AWS JAPAN 生成AIハッカソン] Dialog の紹介
yoshimi0227
0
140
生成AIと知識グラフの相互利用に基づく文書解析
koujikozaki
1
130
VPC間の接続方法を整理してみた #自治体クラウド勉強会
non97
1
790
Automated Promptingを目指すその前に / Before we can aim for Automated Prompting
rkaga
0
110
日経電子版におけるリアルタイムレコメンドシステム開発の事例紹介/nikkei-realtime-recommender-system
yng87
1
480
「 SharePoint 難しい」ってよく聞くけど、そんなに言うなら8歳の息子に試してもらった
taichinakamura
1
590
Featured
See All Featured
Designing for Performance
lara
604
68k
Building Adaptive Systems
keathley
38
2.2k
The Success of Rails: Ensuring Growth for the Next 100 Years
eileencodes
43
6.6k
KATA
mclloyd
29
13k
The Power of CSS Pseudo Elements
geoffreycrofte
72
5.3k
XXLCSS - How to scale CSS and keep your sanity
sugarenia
246
1.3M
Practical Orchestrator
shlominoach
186
10k
Building a Scalable Design System with Sketch
lauravandoore
459
33k
Why You Should Never Use an ORM
jnunemaker
PRO
53
9k
RailsConf 2023
tenderlove
29
880
Cheating the UX When There Is Nothing More to Optimize - PixelPioneers
stephaniewalter
280
13k
個人開発の失敗を避けるイケてる考え方 / tips for indie hackers
panda_program
92
16k
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