daisuke_nomura の日記

Android プログラマーな鉄道ファンのブログ

Kii Cloud の RxJava 2 ライブラリ作った

RxKii

RxKii という Kii Cloud の RxJava 2 ラッパーライブラリを作りました。
RxJava 2 の Completable or Single or Observable を返してきます。

github.com

クラス名は、Kii のクラスに Rx を足したものになってます。
KiiObject -> RxKiiObject

コールバック地獄

Kii Cloud Android SDK は多くの API で同期と非同期の両方が揃っています。
ただ当然ながら、非同期 API を使うとコールバック地獄に陥り、ネストが非常に深くなってしまうので、 RxJava で返すようにしました。

Completable or Single

RxKii では、 Completable で返してくる API が多いです。
これは、 RxKiiUser を見ると分かります。

RxKii/RxKiiUser.java at master · daisuke-nomura/RxKii · GitHub

Completable は返す値がない場合に用いられるので、 save/update/delete は自然と Completable になります。

例外は refresh で、kiiUser.refresh(); は Single を返します。ここも Completable になるはずですが、 KiiUser を返します。 これは、 refresh 後に flatMap で次の処理につなぐだろうという想定でこうしました。

Observable を返すのは KiiUploader/KiiDownloader のみ

Observable を返すのは、 KiiUploader/KiiDownloader をラップしたRxKiiUploader/RxKiiDownloader の transferAsObservable だけです。 非同期 API が返す onProgress をラップし、onNext で進捗状況を返してきます。

RxKii/RxKiiUploader.java at master · daisuke-nomura/RxKii · GitHub

ここで見つけましたが、 Kii Cloud Android SDK の KiiRTransferCallback の onTransferCompleted の 引数 Exception に @NonNull アノテーションが付いていますが、Kii のドキュメントを読むと、この Exception は正常時には null のはずなので、RxKii では null チェックを行っています。

Object Body のアップロード

ここは @Nullable の間違いだろうと Kii のTwitterに報告済みです。

Completable を flatMap で繋ぐ際の注意点

また、 README に書いたサンプルを実行した際に気付きましたが、Completable から Single に繋ぐ際に、 Maybe を経由し、 flatMapSingle すると NoSuchElementException になるので、ご注意。

RxJava 2でNoSuchElementExceptionに遭う件 - Qiita

RxJava で重複を削除する

RxJava では、要素の重複を削除することもできます。
コードは RxJava 2 です。

distinct

distinct メソッドを使うと重複要素を削除できます。

Observable
        .just(1, 1, 2, 1)
        .distinct()
        .blockingForEach(new Consumer<Integer>() {
            @Override
            public void accept(Integer integer) throws Exception {
                Log.d("koko", String.valueOf(integer));
            }
        });

出力結果

koko: 1
koko: 2

distinctUntilChanged

distinctUntilChanged メソッドを使うと、次に重複しない要素が出てくるまでの間、重複が削除されます。

Observable
        .just(1, 1, 2, 1, 1, 2, 1, 1)
        .distinctUntilChanged()
        .blockingForEach(new Consumer<Integer>() {
            @Override
            public void accept(Integer integer) throws Exception {
                Log.d("koko", String.valueOf(integer));
            }
        });

出力結果

koko: 1
koko: 2
koko: 1
koko: 2
koko: 1

オブジェクトも可能

対象がオブジェクトでも可能です。
オブジェクトの場合、 distinct に Function を食わせ、その戻り値が一致してるものが削除されます。

class Koko {
    public String str;

    public Koko(String str) {
        this.str = str;
    }
}
List<Koko> kokoList = new ArrayList<>();
kokoList.add(new Koko("aaaa"));
kokoList.add(new Koko("bbbb"));
kokoList.add(new Koko("aaaa"));

Observable
        .fromIterable(kokoList)
        .distinct(new Function<Koko, String>() {
            @Override
            public String apply(Koko koko) throws Exception {
                return koko.str;
            }
        })
        .blockingForEach(new Consumer<Koko>() {
            @Override
            public void accept(Koko koko) throws Exception {
                Log.d("koko", String.valueOf(koko.str));
            }
        });

出力結果

koko: aaaa
koko: bbbb

参考
ReactiveX - Distinct operator

ナショジオの MARS が面白い

National Geographic の MARS が面白いです。日本語タイトルは「マーズ 火星移住計画」。
hulu で配信中です。

www.hulu.jp

channel.nationalgeographic.com

製作総指揮はロン・ハワードなので、面白いに決まってた。

有人火星探査を取り上げた特集で、2016年時点の各人へのインタビューパートと、有人火星探査を実施する2033年のドラマパートの2パートが交互に連なって構成されてます。
インタビューには SpaceXイーロン・マスクはもちろん、 The Martian (邦題: オデッセイ)の作者や NASA が登場します。

YouTube にも前回までのあらすじだったり、幼いころの主人公が登場する第0話となるドラマが公開されています。

www.youtube.com

www.youtube.com

この MARS は National Geographic の紙面連動企画で、2016年11月号に同じように、有人火星探査と移住生活の特集が組まれています。

ナショナル ジオグラフィック日本版 2016年11月号 [雑誌]

ナショナル ジオグラフィック日本版 2016年11月号 [雑誌]

2015年に成功させた SpaceX のロケット第一ステージの帰還が火星への着陸にも応用できたり、
スペースシャトルは我慢ならないとか、巨大なサターンVロケットが火星のことも考慮されていたのは知りませんでした。

www.youtube.com

サターンV - Wikipedia

南極で1年間生活できないなら火星まで持たないそうなので、僕には無理っぽいです。

Android StudioでBuilderを自動生成する

Android Studioプラグインを追加すると、JavaのBuilderを自動で生成できます。
もちろんIntelliJ IDEAでも使えます。

プラグインはこちら。 github.com

使い方

適当なクラスでGenerateメニューからBuilderを選択。 f:id:daisuke_nomula:20170108025331p:plain f:id:daisuke_nomula:20170108025343p:plain

メソッドを作る対象を選んで、OKを押すだけ。 f:id:daisuke_nomula:20170108025355p:plain

生成されました。 f:id:daisuke_nomula:20170108025408p:plain

インストール方法

Android StudioのConfigureメニューから、Pluginsをクリック。 f:id:daisuke_nomula:20170108024246p:plain

次にBrowse repositories... で開いた後に、検索ボックスでBuilderを検索。

f:id:daisuke_nomula:20170108024300p:plain

"InnerBuilder" を選び、"Install" をクリックしてインストール。

近況

前回の投稿から1年半以上経ちました。

前回参加した勉強会は2015年6月のプロ生松山でした。2016年は参加してません。

ここ1年半ほどAndroidプログラマをしていて、万世橋辺りで強引かつ大幅なコース修正をしてます。

昨年末からAndroidアプリを開発してますが、まだ完成しません。