Upgrade to Pro — share decks privately, control downloads, hide ads and more …

RxJava実践入門

 RxJava実践入門

Reactive Programmingの簡単な説明とAndroidアプリ開発において具体的にどのようにRxJavaを使うのかを説明します。

[参考文献]
- Reactive programming - Wikipedia, the free encyclopedia

https://en.wikipedia.org/wiki/Reactive_programming
- JJUG ナイトセミナーで Reactive Streams について発表しました

http://okapies.hateblo.jp/entry/2015/06/26/024505
- ReactiveX
http://reactivex.io/
- Exploring RxJava 2 for Android (GOTOcph October 2016)

https://speakerdeck.com/jakewharton/exploring-rxjava-2-for-android-gotocph-october-2016
- Reactive Programming with JDK 9 Flow API

https://community.oracle.com/docs/DOC-1006738

979d93b360f80486b121486a9d063ad5?s=128

Hiroshi Kurokawa

January 17, 2018
Tweet

Transcript

  1. 3Y+BWB࣮ફೖ໳ αϙʔλʔζษڧձ
 ࠇ઒༸ !IZESBLFDBU

  2. 2 3Y+BWBͱ͸ w3Y 3FBDUJWF&YUFOTJPO ͷ+BWB࣮૷ w3FBDUJWF

  3. 3 3FBDUJWF1SPHSBNNJOHͱ͸ ˑBQSPHSBNNJOHQBSBEJHNPSJFOUFEBSPVOEEBUBGMPXTBOEUIF QSPQBHBUJPOPGDIBOHF˒ 3FBDUJWFQSPHSBNNJOH8JLJQFEJB IUUQTFOXJLJQFEJBPSHXJLJ3FBDUJWF@QSPHSBNNJOH 3FBDUJWF ر٦ةؿٗ٦׾㹑鎉׃גַ׵ծ㢌刿׾⠗乄ׇׁ׷ 5SBOTGPSNBUJPOBM 㢌䳔㘗

    㢌侧ח㼎ׅ׷乼⡲׾אא鎸鶢
  4. 4 3FBDUJWF1SPHSBNNJOHͱ͸ 5SBOTGPSNBUJPOBM A = 2 B = 3 C

    = (A + 1) x (B - 1) 3FBDUJWF   Y " # $   
  5. 5 3FBDUJWF1SPHSBNNJOHͱ͸ 5SBOTGPSNBUJPOBM 3FBDUJWF   Y " # $

       A = 2 B = 3 C = (A + 1) x (B - 1) A = 3
  6. 6 3FBDUJWF1SPHSBNNJOHͱ͸ 5SBOTGPSNBUJPOBM 3FBDUJWF   Y " # $

       A = 2 B = 3 C = (A + 1) x (B - 1) A = 3
  7. 7 3FBDUJWF1SPHSBNNJOHͱ͸ 5SBOTGPSNBUJPOBM 3FBDUJWF   Y " # $

       A = 2 B = 3 C = (A + 1) x (B - 1) A = 3
  8. 8 ͳͥ"OESPJEΞϓϦ։ൃͰ31͕஫໨͞ΕΔͷ͔ network.getDataA(new NetworkCall.Listener<String>() {
 @Override public void success(String data)

    { network.getDataB(data, new NetworkCall.Listener<String>() {
 @Override public void success(String data) { runOnUiThread(() -> { if (!isDestroyed()) { tv.setText(data);
 } });
 }‌
 
 @Override public void failure(Throwable t) {}
 });
 } @Override public void failure(Throwable t) {}
 });
  9. 9 ͳͥ"OESPJEΞϓϦ։ൃͰ31͕஫໨͞ΕΔͷ͔

  10. 10 3Y+BWBͱ͸ w3Y 3FBDUJWF&YUFOTJPO ͷ+BWB࣮૷ w3FBDUJWF  w3Y

  11. BMJCSBSZGPSDPNQPTJOHBTZODISPOPVTBOEFWFOUCBTFE QSPHSBNTVTJOHPCTFSWBCMFTFRVFODFT˒ 3FBDUJWF9*OUSP IUUQSFBDUJWFYJPJOUSPIUNM 11 3Yͱ͸

  12. BMJCSBSZGPSDPNQPTJOHBTZODISPOPVTBOEFWFOUCBTFE QSPHSBNTVTJOHPCTFSWBCMFTFRVFODFT˒ 3FBDUJWF9*OUSP IUUQSFBDUJWFYJPJOUSPIUNM 12 3Yͱ͸ subscribe

  13. BMJCSBSZGPSDPNQPTJOHBTZODISPOPVTBOEFWFOUCBTFE QSPHSBNTVTJOHPCTFSWBCMFTFRVFODFT˒ 3FBDUJWF9*OUSP IUUQSFBDUJWFYJPJOUSPIUNM 13 3Yͱ͸

  14. BMJCSBSZGPSDPNQPTJOHBTZODISPOPVTBOEFWFOUCBTFE QSPHSBNTVTJOHPCTFSWBCMFTFRVFODFT˒ 3FBDUJWF9*OUSP IUUQSFBDUJWFYJPJOUSPIUNM 14 3Yͱ͸

  15. BMJCSBSZGPSDPNQPTJOHBTZODISPOPVTBOEFWFOUCBTFE QSPHSBNTVTJOHPCTFSWBCMFTFRVFODFT˒ 3FBDUJWF9*OUSP IUUQSFBDUJWFYJPJOUSPIUNM 15 3Yͱ͸ completed

  16. BMJCSBSZGPSDPNQPTJOHBTZODISPOPVTBOEFWFOUCBTFE QSPHSBNTVTJOHPCTFSWBCMFTFRVFODFT˒ 3FBDUJWF9*OUSP IUUQSFBDUJWFYJPJOUSPIUNM 16 3Yͱ͸ Observable subscribe(Subscriber) Subscriber onNext()

    onCompleted() onError()
  17. 17 3Yͱ͸ BMJCSBSZGPSDPNQPTJOHBTZODISPOPVTBOEFWFOUCBTFE QSPHSBNTVTJOHPCTFSWBCMFTFRVFODFT˒ 3FBDUJWF9*OUSP IUUQSFBDUJWFYJPJOUSPIUNM Operator

  18. 18 3Yͱ͸ 1 2 3 4 5 6 < >

    GPSxJO JGx % 2 == 0UIFO QVTIx * x UP list FOE FOE SFUVSOlist
  19. 19 3Yͱ͸ 1 2 3 4 5 6 < >

    GJMUFS x % 2 == 0  NBQ x -> x * x
  20. 20 3Yͱ͸ 1 2 3 4 5 6

  21. 21 3Yͱ͸ 1 2 3 4 5 6 GJMUFS x

    % 2 == 0  NBQ x -> x * x
  22. 22 3Yͱ͸ 1 2 3 4 5 6 GJMUFS x

    % 2 == 0  NBQ x -> x * x 4 16 36
  23. 23 3Yͱ͸ 4 16 36 Observable.just(1, 2, 3, 4, 5,

    6)
 .filter(x -> x % 2 == 0)
 .map(x -> x * x)
 .subscribe(System.out ::println);
  24. 24 3Y+BWBͰͳʹ͕Ͱ͖Δͷ͔ wඇಉظॲཧ w6*Πϕϯτॲཧ wඇಉظॲཧ 6*Πϕϯτॲཧ

  25. 25 3Y+BWBͰͳʹ͕Ͱ͖Δͷ͔ wඇಉظॲཧ w6*Πϕϯτॲཧ wඇಉظॲཧ 6*Πϕϯτॲཧ

  26. 26 3Y+BWBͰͳʹ͕Ͱ͖Δͷ͔ @Override public void onCreate(Bundle savedInstanceState) { …
 subscription

    = network.getDataA()
 .subscribeOn(Schedulers.io())
 .flatMap(data -> network.getDataB(data))
 .observeOn(AndroidSchedulers.mainThread())
 .subscribe(
 data -> tv.setText(data),
 throwable -> Log.e(TAG, throwable.getMessage())
 );
 }
 @Override public void onDestroy() {
 super.onDestroy();
 subscription.unsubscribe();
 }
  27. 27 3Y+BWBͰͳʹ͕Ͱ͖Δͷ͔ @Override public void onCreate(Bundle savedInstanceState) { …
 subscription

    = network.getDataA()
 .subscribeOn(Schedulers.io())
 .flatMap(data -> network.getDataB(data))
 .observeOn(AndroidSchedulers.mainThread())
 .subscribe(
 data -> tv.setText(data),
 throwable -> Log.e(TAG, throwable.getMessage())
 );
 }
 @Override public void onDestroy() {
 super.onDestroy();
 subscription.unsubscribe();
 }
  28. 28 3Y+BWBͰͳʹ͕Ͱ͖Δͷ͔

  29. 29 3Y+BWBͰͳʹ͕Ͱ͖Δͷ͔ wඇಉظॲཧ w6*Πϕϯτॲཧ wඇಉظॲཧ 6*Πϕϯτॲཧ

  30. 30 3Y+BWBͰͳʹ͕Ͱ͖Δͷ͔ 6*؎كٝزⳢ椚 ׅץגWBMJE׌׏׋㜥さך׫ TVCNJUنةٝ׾FOBCMFחׅ׷

  31. 31 3Y+BWBͰͳʹ͕Ͱ͖Δͷ͔ private void setup() {
 input1.addTextChangedListener(new TextWatcher() {
 @Override

    public void onTextChanged(CharSequence s, int start, int before, int count) {
 input1Valid = s.length() > 0;
 validate();
 }
 });
 … }
 
 private void validate() {
 button.setEnabled(input1Valid && input2Valid && input3Valid);
 } 8JUIPVU3Y+BWB
  32. 32 3Y+BWBͰͳʹ͕Ͱ͖Δͷ͔ 8JUI3Y+BWB private void setup() {
 ArrayList<Observable<Boolean >> validators

    = new ArrayList <>();
 validators.add(RxTextView.textChanges(input1).map(s -> s.length() > 0));
 … 
 Observable.combineLatest(validators, args -> {
 for (Object a : args) {
 if (!(Boolean) a) return false;
 }
 return true;
 }).subscribe(button ::setEnabled);
 }
  33. 33 3Y+BWBͰͳʹ͕Ͱ͖Δͷ͔ 8JUI3Y+BWB private void setup() {
 ArrayList<Observable<Boolean >> validators

    = new ArrayList <>();
 validators.add(RxTextView.textChanges(input1).map(s -> s.length() > 0));
 … 
 Observable.combineLatest(validators, args -> {
 for (Object a : args) {
 if (!(Boolean) a) return false;
 }
 return true;
 }).subscribe(button ::setEnabled);
 }
  34. 34 3Y+BWBͰͳʹ͕Ͱ͖Δͷ͔ 8JUI3Y+BWB private void setup() {
 ArrayList<Observable<Boolean >> validators

    = new ArrayList <>();
 validators.add(RxTextView.textChanges(input1).map(s -> s.length() > 0));
 … 
 Observable.combineLatest(validators, args -> {
 for (Object a : args) {
 if (!(Boolean) a) return false;
 }
 return true;
 }).subscribe(button ::setEnabled);
 }
  35. 35 3Y+BWBͰͳʹ͕Ͱ͖Δͷ͔ 8JUI3Y+BWB private void setup() {
 ArrayList<Observable<Boolean >> validators

    = new ArrayList <>();
 validators.add(RxTextView.textChanges(input1).map(s -> s.length() > 0));
 … 
 Observable.combineLatest(validators, args -> {
 for (Object a : args) {
 if (!(Boolean) a) return false;
 }
 return true;
 }).subscribe(button ::setEnabled);
 }
  36. 36 3Y+BWBͰͳʹ͕Ͱ͖Δͷ͔

  37. 37 3Y+BWBͰͳʹ͕Ͱ͖Δͷ͔ wඇಉظॲཧ w6*Πϕϯτॲཧ wඇಉظॲཧ 6*Πϕϯτॲཧ

  38. 38 3Y+BWBͰͳʹ͕Ͱ͖Δͷ͔ ꬊず劍Ⳣ椚 6*؎كٝزⳢ椚

  39. 39 3Y+BWBͰͳʹ͕Ͱ͖Δͷ͔ ꬊず劍Ⳣ椚 6*؎كٝزⳢ椚 أؙٗ٦ָٕ⨡姺׃׋׵ꬊず 劍Ⳣ椚׾㨣׭ծأؙٗ٦ָٕ Ꟛ㨣׃׋׵װ׭׷ ؕؐٝزָחז׏׋׵ 穠卓ָ邌爙ׁ׸׷

  40. 40 3Y+BWBͰͳʹ͕Ͱ͖Δͷ͔ ConnectableObservable<Boolean> idling =
 RxAbsListView.scrollEvents(listView)
 .map(event -> event.scrollState()
 ==

    AbsListView.OnScrollListener.SCROLL_STATE_IDLE)
 .distinctUntilChanged()
 .publish(); أؙٗ٦ٕךꟚ㨣⨡姺׾嗚濼ׅ׷0CTFSWBCMF
  41. 41 3Y+BWBͰͳʹ͕Ͱ͖Δͷ͔ أؙٗ٦ٕךꟚ㨣⨡姺׾嗚濼ׅ׷0CTFSWBCMF ConnectableObservable<Boolean> idling =
 RxAbsListView.scrollEvents(listView)
 .map(event -> event.scrollState()


    == AbsListView.OnScrollListener.SCROLL_STATE_IDLE)
 .distinctUntilChanged()
 .publish();
  42. 42 3Y+BWBͰͳʹ͕Ͱ͖Δͷ͔

  43. 43 3Y+BWBͰͳʹ͕Ͱ͖Δͷ͔ أؙٗ٦ָٕ⨡姺׃׋׵ꬊず劍Ⳣ椚׾Ꟛ㨣ׅ׷ final Subscription s = idling.startWith(true)
 .filter(b ->

    b)
 .flatMap(aBool -> serivce.getData())
 .subscribe(l -> showLog("Success!"));
  44. 44 3Y+BWBͰͳʹ͕Ͱ͖Δͷ͔ أؙٗ٦ָٕꟚ㨣׃׋׵ꬊず劍Ⳣ椚׾⨡姺ׅ׷ final Subscription s = idling.startWith(true)
 .filter(b ->

    b)
 .flatMap(aBool -> serivce.getData()) .takeUntil(idling.filter(b -> !b))
 .repeatWhen(completes -> completes.switchMap(
 c -> idling.filter(b -> b)))
 .subscribe(l -> showLog("Success!"));
  45. 45 3Y+BWBͰͳʹ͕Ͱ͖Δͷ͔ أؙٗ٦ָٕꟚ㨣׃׋׵ꬊず劍Ⳣ椚׾⨡姺ׅ׷ final Subscription s = idling.startWith(true)
 .filter(b ->

    b)
 .flatMap(aBool -> serivce.getData()) .takeUntil(idling.filter(b -> !b))
 .repeatWhen(completes -> completes.switchMap(
 c -> idling.filter(b -> b)))
 .subscribe(l -> showLog("Success!"));
  46. 46 3Y+BWBͰͳʹ͕Ͱ͖Δͷ͔

  47. 47 3Y+BWBͰͳʹ͕Ͱ͖Δͷ͔ أؙٗ٦ָٕ⨡姺׃׋׵ⱄTVCTDSJCFׅ׷ final Subscription s = idling.startWith(true)
 .filter(b ->

    b)
 .flatMap(aBool -> serivce.getData()) .takeUntil(idling.filter(b -> !b))
 .repeatWhen(completes -> completes.switchMap(
 c -> idling.filter(b -> b)))
 .subscribe(l -> showLog("Success!"));
  48. 48 3Y+BWBͰͳʹ͕Ͱ͖Δͷ͔

  49. 49 3Y+BWBͰͳʹ͕Ͱ͖Δͷ͔ 㹋遤ׅ׷أٖحس׾䭷㹀ׅ׷ final Subscription s = idling.startWith(true)
 .subscribeOn(Schedulers.io())
 .filter(b

    -> b)
 .flatMap(aBool -> serivce.getData())
 .takeUntil(idling.filter(b -> !b))
 .repeatWhen(completes -> completes.switchMap(
 c -> idling.filter(b -> b)))
 .observeOn(AndroidSchedulers.mainThread())
 .subscribe(l -> showLog("Success!"));
  50. 50 3Y+BWBͰͳʹ͕Ͱ͖Δͷ͔ ConnectableObservable<Boolean> idling =
 RxAbsListView.scrollEvents(listView)
 .map(event -> event.scrollState()
 ==

    AbsListView.OnScrollListener.SCROLL_STATE_IDLE)
 .distinctUntilChanged()
 .publish();
 subscriptions.add(idling.connect());
 
 subscriptions.add(idling.startWith(true)
 .subscribeOn(Schedulers.io())
 .filter(b -> b)
 .flatMap(aBool -> serivce.getData())
 .takeUntil(idling.filter(b -> !b))
 .repeatWhen(completes -> completes.switchMap( c -> idling.filter(b -> b)))
 .observeOn(AndroidSchedulers.mainThread())
 .subscribe(l -> showLog("Success!")));
  51. 51 3Y+BWBͷϝϦοτσϝϦοτ ًٔحز ˖ ؎كٝزװꬊず劍Ⳣ椚ָ䪔ְװְׅ ˖ 朐䡾㢌侧ָ㼰זֻג幥׬ ˖ ر٦ةؿٗ٦ך鋅鸐׃ָ葺ֻז׷ رًٔحز

    ˖ 湫䠬涸הכꣲ׵זְ ˖ ⢪ְֿזׅחכ䢪׸ָ䗳銲 ˖ ➬穈׫׾椚鍑׃גְזְה縐ח䅹׶װְׅ
  52. 52 ࢀߟ ˖ 3FBDUJWFQSPHSBNNJOH8JLJQFEJB UIFGSFFFODZDMPQFEJB
 IUUQTFOXJLJQFEJBPSHXJLJ3FBDUJWF@QSPHSBNNJOH ˖ ++6(ش؎زإىش٦ד3FBDUJWF4USFBNTחאְג涪邌׃ת׃׋
 IUUQPLBQJFTIBUFCMPKQFOUSZ ˖

    3FBDUJWF9
 IUUQSFBDUJWFYJP ˖ &YQMPSJOH3Y+BWBGPS"OESPJE (050DQI0DUPCFS 
 IUUQTTQFBLFSEFDLDPNKBLFXIBSUPOFYQMPSJOHSYKBWBGPS BOESPJEHPUPDQIPDUPCFS ˖ 3FBDUJWF1SPHSBNNJOHXJUI+%,'MPX"1*
 IUUQTDPNNVOJUZPSBDMFDPNEPDT%0$