AndroidでgRPCを触ってみて辛かったこと


触ってみたのでまとめてみます。アプリ(Android)から見た内容です。
実装方法についてこちらでは記載していません。他の記事が詳しいのでそちらをご覧ください。

記載時のgRPCのバージョンは 1.4 です。

なぜgRPCを使おうと思ったのか

  • jsonは補足資料を別途作る必要があり手間がかかる。
  • 型が使えるのでコーディングしやすそう。
  • パフォーマンスが良い(らしいです。)
  • 流行りに乗ってみたかった
  • google製

使ってみてどうだったか?

よかったこと

  • 型を持っているのでコーディングしやすい。
  • gRPCを経由して最初からデータが入ったクラスを取得できます。jsonをクラスに変換処理が不要。
  • データが入ってたらboolean返してくれる便利メソッドとか最初から使えるのでコーディングが楽。
  • サーバ側でprotoファイル(通信でやり取りするオブジェクトの定義ファイル)をアプリ側にセットする。サーバとクライアントの間でAPI仕様を合わせることが簡単。
  • 速度もjsonと遜色ないです。(ちゃんと調べたら早いのかな?)

辛かったこと

  • 日本語資料が少なく、ネットにも情報が多くなかったので時間がかかる。
  • ActivityからFragmentへのデータ引き渡し
  • 一定時間経過するとException(End of Stream)が発生。通信ができなくなります。
  • デバッグがやりづらい。(エンジニア以外)

辛かったことへの対処

日本語資料が少なく、ネットにも情報が多くなかったので時間がかかる。

  • 色々な会社が採用進めているらしいので徐々に増えてくると思いますが、現状は試行錯誤が必須でしょうか。もう少しトラブル系の情報が増えて欲しい。
参考資料

ActivityからFragmentへのデータ引き渡し。

  • Fragmentに値を渡すときBundle使ってますよね?BundleのputSyrializable()にセットする値は、toByteArray()とparseFrom()を使いました。byte[]であればFragment再生時もonSaveInstanceState()にそのまま保存できます。
    private byte[] byteArray;


    public static SampleFragment newInstance(GrpcResponse grpcResponse){
        SampleFragment f = new SampleFragment();
        Bundle b = new Bundle();
        b.putSerializable(BUNDLE_KEY_HOGE, grpcResponse.toByteArray());
        f.setArguments(b);
    }

    @Override
    public View onViewCreated(View v, Bundle savedInstanceStates){
        if (savedInstanceState == null) {
            byteArray = (byte[]) getArguments().getSerializable(BUNDLE_KEY_HOGE);
        } else {
            byteArray = (byte[]) savedInstanceState.getSerializable(BUNDLE_KEY_HOGE);
        }

        try {
            response = GrpcResponse.parseFrom(byteArray);
        } catch (InvalidProtocolBufferException e) {
        }
    }

    @Override
    public void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        outState.putSerializable(BUNDLE_KEY_HOGE, byteArray);
    }

初めはこのメソッドを知らずにSerializableをimplementsしたラッパークラスを作って使っていたのですが、Activityが再生成されたタイミングで、onSavedInstanceState()で保存したオブジェクトがnullになる事象が発生しました。

初回のサーバ接続から一定時間が経過するとException(End of Stream)が発生。通信が失敗する。

  • エラー内容
  • APIリファレンス見るとアプリとサーバの接続状態を確認するメソッドがあるらしいのですが、まだ未実装のようです。そのため、channelを毎回作成して接続を貼り直して対応してます。Go言語だと問題ないのでしょうか(未確認)。

デバッグがやりづらい

  • gRPC経由のデータはブラウザで確認ができないため、エンジニア経由でデータの中身が確認できなかったです。ただ、未確認ですが、jsonに出力もできるようなので、上手く使えれば解決するかも知れません。

おわりに

  • 色々悩まされましたがメリットも大きいと感じました。Retrofit要らずです。もっと情報増えてくると嬉しいですね。