blog

DeNAのエンジニアが考えていることや、担当しているサービスについて情報発信しています

2023.01.31 技術記事

Flutter で Voice Pococha アプリを1年間開発して感じたこと

by Kaisei Sunaga

#voice-pococha #flutter #performance #ios #android

こんにちは、ぎもちんです。
音声ライブ配信サービス Voice Pococha のクライアントアプリ開発を担当しています。

Voice Pococha は、 2023/1/17 をもって1周年を迎えることができました。
今回は、 Voice Pococha で Flutter を採用し、実際に1年間運用したことで感じた、 Flutter で良かった点や、課題感などをいくつかピックアップしてご紹介します。

開発スピードの高速化と、工数の削減

Flutter を採用したことで感じた一番のメリットは、開発スピードです。

Voice Pococha には、以下のような様々な機能があります。

  • 配信・視聴
  • イベント
  • ランキング
  • プロフィール
  • などなど…

こういった機能のほとんどが、 Flutter を用いて開発されています。

参考までに、こちらのコードの内訳を見ていただくとわかりやすいです。

コードの内訳

コードの内訳

執筆時点で Dart が 82% を占めています。
Flutter Plugin として切り出している機能や、アセット等の細かいデータを除いても、 Voice Pococha の半分以上の機能がシングルコードベースで実現されていることがわかります。 🎉

多くの機能を Dart で記述できたため、この1年間でさまざまな機能をスピーディーに開発し、リリースに繋げられました。

例えば、 Voice Pococha はリリース当初、 iOS のみ対応していましたが、 2022年6月に Android 版リリースを行いました。
Android 版の開発は、検証期間を含めて3ヶ月弱で完了したため、非常にスピーディーな開発が行えたと思います。
この期間は主に音声処理や通知といった、 Flutter でカバーしきれない部分の開発がメインとなっており、 UI に関する実装はほとんど行なっていません。

このように、 Android への展開が短期間で行えたのは、 Flutter の力があってこそに感じています。

デザイン反映・修正の高速化

Flutterの有名な機能に、 Hot Reload というものがあります。
コードを保存すると、即座にUIやロジックが反映される機能です。

この Hot Reload 機能は、デザイナーとのコミュニケーション円滑化に役立っています。

この記事を読まれている方の中には、デザイナーに開発中のアプリを見せて、細かなマージン調整やアニメーションの調整などを行った経験のある方がいるかと思います。
このときに、毎回ビルドをするのでは、手間と時間がかかりすぎたり、画面にたどり着くために手順が必要だったりと大変ではありませんか?

Hot Reload を使うと、デバッグ中のアプリ画面を共有しながら、こういった調整作業を効率よく行えます。
いちいちビルドしたり、画面を開き直したりする手間も無くなるので、サクッと相談できてとても便利です。

Flutter には Hot Reload 以外にも、 DevTools といった機能も用意されています。
こちらを使えば、 Widget のレイアウトや描画内容等を細かく調べることができます。

このような周辺機能が充実している点が、デザイン反映や修正を高速化する上で非常に役立っていると感じます。

余談

Voice Pococha は Dart のコード量が 21 万行ほどありますが、この環境下でも Hot Reload は1秒未満ほどで高速に動作しています。
(M1 Max の MacBook Pro にて計測)

これはたまたま高速に動作している訳ではなく、しっかりと裏側で最適化された実装が行われているため、高速に動作しています。
こちらの記事に仕組みが詳しく書かれているため、興味のある方はぜひ一読されると面白いかと思います。

Flutter Hot Reload

Platform View による、柔軟なアプリ構築

Flutterには、 Platform View と呼ばれる機能もあります。

Flutter は Skia を用いて自前でUIを描画しているため、 Android や iOS に存在するUI系のリソースを再利用することが難しいです。
しかし、 Flutter だけでは実現の難しい View もあるため、どうしてもそういった View を組み込む必要が出てくる場面があります。
(例えば、 WebView や 動画再生View などが、 Flutter で実現の難しい View に該当します)

そこで Platform View の出番です。
この機能により、 iOS の UIView や、 Android の View といったネイティブ側の View を、 Flutter の Widget として組み込むことができます。

Voice Pococha アプリ内では、アイテムエフェクトの再生や、一部のアニメーション表示に使用されています。

Platform View を用いたアイテムエフェクト再生

Platform View を用いたアイテムエフェクト再生

Platform View を使う上で気をつける点

Platform View を採用する上で、気をつけるべき点が3つほどあります。

  • パフォーマンスの悪化
  • 機能の制約
  • 動作の安定性

これらについて、それぞれ説明します。

パフォーマンスの悪化と、機能の制約

まずパフォーマンスの悪化と機能の制約ですが、 Voice Pococha では Android のフレームレートが問題になっています。

Android の Platform View には、 Hybrid CompositionVirtual Display の2種類の組み込み方法があります。
(Flutter 3.0 から、 Texture Layer Hybrid Composition と呼ばれる方法も追加されていますが、ここでは省略します)

Hybrid Composition は、 Android 10 未満の環境でのパフォーマンスが非常に悪いです。
しかし、機能面の制約が少ないため、例えばキーボード入力の伴う WebView が必要な場合などでは、 Hybrid Composition が必要になります。

一方 Virtual Display は、高速に動作するためパフォーマンス面の影響はそこまで大きくありません。
ですが、アクセシビリティ面のサポートがなかったり、一部の機能に制約があるため使用できる場面が限定されます。

実際に、 Voice Pococha のアイテムエフェクトにおけるパフォーマンスを Android 8 端末で調べた結果がこちらです。

Virtual Display と Hybrid Composition の比較

Virtual Display と Hybrid Composition の比較

図の上段がラスタースレッド、下段がUIスレッドのパフォーマンスになります。
どちらも時間が短ければ短いほど、高いフレームレートでの描画が行えます。

少し見ずらいと思いますが、 UIスレッドの速度はほとんど同じなものの、ラスタースレッドの速度が、

  • Virtual Display: 最大 22.6ms/frame 、平均 13.5ms/frame
  • Hybrid Composition: 最大 70.9ms/frame 、平均 43.0ms/frame

となっており、 Hybrid Composition よりも Virtual Display の方が、約3倍ほど高速な結果となっています。

そのため、 Android 10 未満をサポートしているアプリの場合は

  • 機能に制約が少ない方が良い場合は Hybrid Composition
  • パフォーマンスが重要であれば Virtual Display

のように、適材適所で組み込み方法を選ぶ必要があります。

動作の安定性

続いて、動作の安定性についてです。
こちらは、 Android と iOS のどちらにも言える課題点かなと捉えています。

例えば、Voice Pococha では以下のような不具合に遭遇しています。

  • Platform View を使った画面から、別の画面へ遷移すると、前の画面が一瞬だけチラつく
  • Platform View の上にオーバーレイを重ねると、その箇所だけ色が濃くなる
  • Platform View の描画位置や順序がおかしくなる

こういった不具合は、 Flutter のバージョンを上げると治るものもあれば、逆にデグレしてしまうこともありました。
この原因としては、 Platform View の仕組み自体が複雑なためだと感じています。

Platform View のほとんどの実装は、基本的に C++ で記載されているため、 Dart ではなく C++ のコードを読み解く必要があります。
加えて、読み解いて修正できたとしても、修正したフレームワークを配布する必要性が出てくるため、非常に手間がかかってしまいます。

Platform View のまとめ

Platform View は非常に強力な機能である一方、制約やいくつかの不具合があったり、パフォーマンスの懸念点があるなど、 Flutter アプリ開発において負債になる可能性があります。
そのため Flutter の Widget で実現できる機能は、極力 Platform View を使うべきではないでしょう。

Voice Pococha では Platform View を採用する前に、

  1. そもそも Platform View を使う必要が本当にあるか( Widget で実現できないか)
  2. 仕様を調整をすることで解決できないか
  3. 機能面の制約や、パフォーマンス影響を許容できるか

といった、いくつかの注意事項を念頭において、なるべく Platform View を使わない方針で考えています。

上で述べたような、「気をつけるべき点」を押さえて、
本当に必要な場面で Platform View を採用することで、メリットを最大限に活かした高速な開発が行えると感じています。

バージョン更新への追従

モバイルアプリ開発では、最新バージョンのOSや周辺パッケージへの追従が欠かせません。
ここでは Flutter を使ったことで、最新バージョンへの追従が難航した部分についてご紹介します。

in_app_purchase パッケージの更新

Voice Pococha では、課金処理に in_app_purchase パッケージを使用しています。
こちらのパッケージは Plugin 形式になっており、内部的に Android では Google Play Billing を、 iOS では StoreKit を使用しています。

Voice Pococha では、 Google Play Billing バージョン3を当初使用していましたが、 サポート終了のアナウンス がありました。
そのため、バージョン4へ更新する必要があり、間接的に in_app_purchase パッケージの更新が必要となりました。

しかし、 in_app_purchase パッケージを更新すると、 iOS 側の課金処理も更新されるため、 iOS での検証も必要になります。
また、使用している Flutter バージョンの都合で、最新の in_app_purchase パッケージが導入できないといった問題も発生しました。

幸い、ライブラリ更新が必要なことは早い段階で把握していたため、 iOS と Android のどちらも検証をする工数は確保できました。
また、最新のパッケージではなくとも、途中のバージョンまで更新をすれば、 Google Play Billing ライブラリをバージョン4以降にすることができるため、こちらも無事対応できました。

iOS 16 への対応

iOS 16 への対応は以下の issue が主な原因となり、 iOS 16 で絵文字と一部のテキスト入力時にクラッシュする不具合が発生しました。
https://github.com/flutter/flutter/issues/111494

この不具合は、 iOS 16 リリースから約1ヶ月後に、 Flutter 3.3.5 で修正されています。

ですが、 Voice Pococha では Flutter 3 系 で発生していた Platform View やその他の細かい不具合により、 Flutter 2 系からの更新ができていませんでした。
急遽 Flutter 更新の伴う開発やQAの工数を確保することも難しく、 Flutter 3.3.5 への更新ができない状況に陥りました。

暫定対応として、 iOS のテキスト入力処理を、 UITextFieldUITextView の2種類を用いて Platform View で丸ごと置き換える形で対応しました。
結果、クラッシュは治りましたが、テキスト入力系の処理をシングルコードベースで実現しづらくなってしまいました。

バージョン更新で感じた課題

Flutter Plugin パッケージの更新は、 iOS と Android の両OSで検証が必要となるため、その点に注意が必要に感じました。

特に、 Google Play Billing のようなサポート期間があるものは、スケジュールを遵守する必要があります。
更新を見落としたり、更新に間に合わなかった場合は、事業リスクにも繋がる可能性があるためです。

パッケージを導入する際は、 iOS と Android で依存しているライブラリを把握しておき、バージョンやサポート期限等を管理する必要があると感じました。

また、 OS のバージョン更新では予期しない不具合が発生することがあるため、

  • テキスト処理
  • 入力処理
  • レンダリング処理
  • プラグイン処理

といった箇所に、注意が必要に感じています。

最後に

Voice Pococha では、この1年間 Flutter の機能をフル活用したアプリ開発を行いました。
こちらの記事に書ききれていないこともたくさんあるため、今後も情報発信していければと思います。

ぜひこちらの記事が、 Flutter を採用するか検討中の方や、Flutter を実運用する上で困っている方の参考になれば幸いです。

参考文献

最後まで読んでいただき、ありがとうございます!
この記事をシェアしていただける方はこちらからお願いします。

recruit

DeNAでは、失敗を恐れず常に挑戦し続けるエンジニアを募集しています。