Inside BuildIt

株式会社ビルディットのデザイナー・エンジニアによるブログです

ふりかえりを習慣化するアプリ「Stockr(ストッカー)」のFlutter開発ストーリー

f:id:tamaki1226:20210413182136p:plain

弊社では昨年9月にふりかえることで思考の”質”を高めるアプリ「Stockr」をリリースしました。
そこで、Flutterを用いた開発エピソードをご紹介します。

自己紹介

こんにちは、エンジニアの河村です。大学4年次からアルバイトで参画し、Stockr開発をメインで担当しています。この4月から正式入社となりました!
最近、VR(Oculus Quest2)を購入しまして、運動不足解消に励んでいます💦

Flutterを採用した経緯

Flutter では、クロスプラットフォーム技術によりAndroidとiOSを同時に開発することが出来ます。また、ソースコードを保存すると、リアルタイムでアプリに反映されるHot Reloadや宣言的UIをフレームワークでサポートしていることや、標準のMaterial Designが充実しているため、開発工数の短縮ができる見込みがありました。

工数短縮により、検証サイクルを早く回せることは大きなメリットです。実際に私がフルタイムでコミットしていない状態で、開発開始から3ヶ月でファーストリリースが出来ました。

また、弊社では月に一度、気になる技術を共有するゆるはち .itという勉強会を運営しており、そこでも既に2度Flutterをテーマに開催していました。注目されている技術であることや社内のFlutterへの感触が良かったことも採用のキッカケになりました。

yuruhachi-it.connpass.com

技術スタックについて

f:id:tamaki1226:20210413174218p:plain

Stockrは上記の図のように、主にGooge Cloud Platform + Flutterで開発しました。
特にFirebaseをフル活用しており、バックエンドの機能をFirebase内で完結させています。

  • データベース: Firebase Cloud Firestore

  • 認証: Firebase Authentication

  • 通知: Firebase Cloud Messaging

  • 処理の定期実行: Firebase Cloud Functions

  • ディープリンク(スマホアプリヘ直接遷移する仕組み): Firebase Dynamic Links

  • アプリの設定等: Firebase Remote Config

  • ファイルサーバ: Google Cloud Storage

  • エラートラッキング: Firebase Crashlytics

  • アナリティクス: Google Tag Manager, Google Analytics, Google BigQuery

  • 国際化対応: Google スプレッドシート(文字列の管理),Google Apps Script(Spread SheetをもとにDartファイルを生成)

  • テストビルド配信: Firebase App Distribution

  • ユーザサポート: Slack

また、国際化対応しているため、15分置きにCloud Functionsを定期実行しタイムゾーンの考慮をしました。(通知や定期的なアプリ内イベントの実行に関わっています)

状態管理について

Flutterにおいて、画面の状態管理を行う場合の第1選択肢は、StatefulWidgetです。StatefulWidgetを用いた状態管理はユーザの操作に応じてsetStateを呼ぶことで、能動的にリビルドをすることで実現されます。

しかしながら、StatefulWidgetを用いる場合は状態の値をWidget間で受け渡し(いわゆるバケツリレー)をしなければいけません。

それを回避するために、状態管理にRiverpod + StateNotifier + Flutter Hooks + Freezed を採用しました。

なお、途中から状態管理の仕組みを変えるにはコストが掛かるため、ルールとしてStatefulWidgetは使わないという方針を共有し開発を進めました。

Freezedについて

Freezedを用いることで、immutableなオブジェクトのコード生成することができます。

Freezedのメリット

  • immutableなオブジェクトは生成してから状態が不変なため、値が変化する心配がなくなります。(どこからアクセスしても同じ結果が返されるため、堅牢なコードを書くことができます)

  • 状態変更を通知するときにFreezedにより作られるcopyWithのメソッドを用いることで、コードをシンプルに保つことができます。(レシーバをコピーし、copyWIthに渡した引数のみを変更したものが返されます)

Flutter Hooksについて

Flutter Hooksは以下の処理をするときに用いるパッケージです。

  • providerの呼び出し

  • react hooksのような機能

Flutter Hooksを用いることで、全体的に簡潔なコードを書くことができます。

Flutter採用で苦労したこと

開発にあたって発生したFlutter特有のトラブルを紹介します。

キーボード入力で環境によってバグがある

Flutterのキーボードにおいて、特定の状況下で変換範囲がハイライトされない、文字の背景色を指定すると高さにバラツキがあるバグがありました。

f:id:tamaki1226:20210413175823p:plain

Stockrではキーボード利用がメインの機能となるため、ネイティブ対応をすることで解消しました。

具体的には、FlutterではMethodChannel を用いることで、プラットフォーム固有のAPIにアクセスすることで解決しました。

まだ黎明期である

iOSでビルドの手順が複雑、WebViewが不安定といった問題がありました。どちらも今後のアップデートで解消されていくようです。アップデートの多さもFlutterの嬉しいところです。

developers.googleblog.com

実装例がネイティブアプリ(Swift, Kotlin)と比べ少ない

登場して間もないフレームワークということもあり、知見が十分に溜まっていません。また、ネイティブでの実装と比較し、Flutterでは簡単に導入できない場合もあります。(AR,決済などのプラットフォーム固有な機能にアクセスする必要があるケース)

最新の技術やニッチなことを実現する場合は、開発コストがかかる傾向があると思います。

さいごに - Stockrと今後について

日常で思いついたアイデアや思考はなにもしなければそのまま頭から流れてしまいます。 「自分と向き合って思考を整理すること」や「考えたことを深めること」も忙しい日常では意識的にとることが難しいと感じます。

Stockrは生活に「思考を貯め」「ふりかえる」きっかけを提供します。日常的に使っていただくことで、自分の知見や経験を客観視でき自己理解を深めることができます!

まだまだサービスの改善中ではありますが、皆様からご意見をいただきながらアップデートしていく所存です。ぜひスマホにインストールして 日々の気づきを書きためてみてください!

stockr.bldt.jp

ダウンロードはこちらから

GooglePlayBadge

ApplePlayBadge