LayerXのFintech事業部(三井物産デジタル・アセットマネジメント(MDM)に出向中)に所属しています、ソフトウェアエンジニアの id:kikuchy です。最近ようやく自室にエアコンを導入しました。今年は熱中症対策バッチリです。
さて、先日FlutterNinjas 2025というイベントが開催されたので、参加してきました。
日本と海外のFlutterエンジニアの架け橋になることを目的とした、主に日本国内の英語話者をターゲットとしたグローバルなFlutterカンファレンスです。 セッションは全編英語で、登壇者のほとんどが日本国外からいらしたエンジニアの皆様でした。 聴講者も半数程度が日本国外の方々で、アメリカやインド、ブラジルなど様々な国からやってきた人々で賑わっていました。
特に気になったセッションをいくつかピックアップしてご紹介します。
Seamless Passkey Authentication with Flutter x Firebase
@heyhey1028 さんと Kyo Yamamoto さんによるセッションでした。
パスキーはパスワードに代わる認証技術で、生体認証などを用いて「操作をしているのがユーザー本人である」ことを認証するものです。 パスワードといった知識認証と比較して漏洩しづらいというセキュリティ的な利点があります。また覚える必要がなくUX的にもメリットがあります。
このセッションではFlutterのプラグインやFirebasseのCloud Functions, Hostingを用いて簡単にパスキー認証を実現する方法を紹介していました。
Building Flutter Apps with AI capabilities without Connection, Bills and Privacy Concerns
@ShuregDenisov さんによるセッションでした。
GoogleのオープンソースモデルGemmaを活用したオンデバイスAIの実装について解説がありました。 Gemmaの軽量モデルはオンデバイスで動作させられるため、プライバシーの保護やコスト削減に一役買います。
中でも、2025年にリリースされたGemma 3nは使用GPUリソースが少なく、多言語対応が強化されているとのことでした。 mediapipeとflutter_gemmaパッケージを使用することで、インターネット接続やサーバーコストを必要としないAI機能の実装が簡単に実現できるとのことです。
Decoding Dart: A Look at the DartVM
@iamjideguru さんによるセッションでした。
Flutterの特徴の一つに、Hot Reloadによって高速にコードを反映、開発イテレーションを短縮できる開発者体験の良さがあります。 また、開発時はHot Reloadを可能にしつつ、製品にする際にはコンパイルし最適化をかけた状態になります。 こうした柔軟なコードの取り扱いを可能にしているのがDart VMです。 このセッションではDart VMの中身について、複数の角度からわかりやすい概説がありました。
中でもDart VMのランタイムの仕組みについてが興味深かったです。 Dart VMは並行性の実現のため、イベントループを使った処理の仕組みを持っています。 一つ一つのIsolateがイベントループを保持しており、Isolateを複数立てることでマルチスレッド処理のようなことが可能になります。 一つのイベントループは、次以降に処理を行うイベントを保持するEvent Queueを持っています。ここまではNode.jsのランタイムやAndroidのLooperとMessageQueueのようによく見る構造です。 Dart MVはそれに加えてMicrotask Queueというキューを持っています。 MicrotaskはEventより優先して処理されるもので、Eventの処理の最中に行いたい非同期処理がこれにあたります。 Futureで関数をラップするだけの処理と、scheduleMicrotask 関数で記述された処理の違いについて明確な理解がなかったので、勉強になりました。
Let's Talk About Memory Leaks in Dart And Flutter
@mhadaily さんによるセッションでした。
FlutterはDart言語のフレームワークで、Dart言語では生成されたオブジェクトはガベージコレクタによって自動的に解放されます。 が、保持の仕方によってはいつまでもオブジェクトが解放されずに、メモリを圧迫することも。 このセッションではどんな時にオブジェクトが解放されないのか、どうしたらそれを防げるのかの説明がありました。
Dart VMのガベージコレクタはマークアンドスイープのアルゴリズムで動作しています。Root Objectからオブジェクトをたどりマークを付け、一巡りでマークできなかったオブジェクトを不要なものとして解放します。 通常はWidgetのbuildメソッド内で生成するオブジェクトはbuildメソッドのスコープでライフタイムを終えることが多いかと思います。 が、buildメソッド内でBuildContextを、より上位のElementやグローバルスコープのメンバに持たせるなどすることで、BuildContextの実態であるElementを、そのツリーごと生き残らせてしまうことがあります。
Widget build(BuildContext context) { // グローバル変数someGlobalHandlerの無名変数がBuildContextをキャプチャして保持し続ける例。 // このbuildメソッドを持ったWidget(に対応するElement)がツリーから外されても、グローバルスコープに上位Elementがツリー構造を保ったままメモリに保持されてしまう。 // 対応策としては、 Nagivator.of(context) の結果得られるNavigatorStateを無名変数にキャプチャさせる方法がある。 someGlobalHandler = () => Navigator.of(context).pop(); ... }
他にも、Finalizerを使用したクリーンナップ、WeekReferenceを使用した弱参照の活用、Listの結合で起きるメモリアロケーションのパターンと速度の比較など、話題は盛りだくさんでした。
Mastering Shortcuts in Flutter: Building Desktop and Web Applications with Advanced Keyboard Support
@ma_freud さんによるセッションでした。
FlutterはモバイルだけでなくWebやデスクトップのアプリも作成することができます。 特にPCから操作される際には物理キーボードがあることが多いため、キーボードショートカットによって、高速な操作を可能にしたり認知負荷を低減することによってUXを向上できます。 このセッションではキーボードショートカットの実装の仕方から、実現のメカニズムまで詳細な説明がありました。
キーボードショートカットに関連する3つの概念があります。
- Intent ... キー押下が意図する、アプリケーションの動作(例:画面内容を更新する)
- Shortcuts ... 押下されるキーとIntentの組み合わせを宣言(例:Cmd + R → 画面内容を更新する)
- Action ... Intentが発行された時に行われる実際の動作(例:APIを叩いて、特定画面の状態を新しいものに置き換える)
これらを用いることでショートカットを実現でき、かつ、ActionとIntentを分離することで、Widgetの実装が膨れずにスリムな状態を保つことができる、とのことでした。
State Restoration – Making The Dead State Live Again
@mastersam_ さんによるセッションでした。
低スペック端末である場合や、フォアグラウンドにいるアプリがリソースを圧迫している場合、OSはバックグラウンドのアプリのプロセスを終了することがあります。 そうして終了された後にアプリがフォアグラウンドに復帰する場合、Flutterアプリはどのように状態を復元するのか、どう実装すると状態を保持できるのかの解説がありました。
基本的に復帰できるものは各Widgetのstateと、Navigationスタックになります。
自作のStatefulWidgetのstateを退避・復帰させるには、 Stateに RestorationMixin をmixinし、RestorableProperty 継承クラスに値を保持させる必要があります。 実装方法はFlutterのドキュメントに記載がありますのでご参照ください。(iOS / Android)
Navigationについては、通常は命令的画面遷移( push
など)を使用した場合はNavigationスタックが復帰されません。
restorablePush
といった、復帰ができる命令的画面遷移メソッドが用意されているため、復帰が必要な画面遷移にはこれを使用すると良いでしょう。
詳しい状態復帰の条件は Navigation クラスのドキュメントに解説があります。実装の際はご覧になってください。
Macros are dead. What now?
@remi_rousselet さんによるセッションでした。
Remiさんは言わずと知れた riverpod パッケージや freezed パッケージの作者です。 Dartの言語機能として導入が検討されていたmacro機能ですが、今年の年初に導入を断念したとの発表がありました。 macroがあれば riverpod や freezed は更に便利ものになると見込まれていたため、macroについてと、今後考えられる進歩の方向性についてお話がありました。
Dartの型(Type)の構造に依存する何かしらの動作をプログラマチックに実現する際は、reflectionを使用してアプリケーションの動作中にTypeの構成情報を取得する動的な手段と、 ソースコードを解析した結果からあらかじめコードを生成しておく静的な手段があります。 macroはこの中間として、コンパイル時に自動的にコード生成がされる手段です。 しかし、ホットリロードと共存させる際に十分なパフォーマンスが出ず、導入は断念されることになりました。
macroが頓挫した後、表記を更に簡略化・明快化できる言語機能として検討されているものとして以下が紹介されました。
また、 build_runner に代わるものを自作して高速化することも考えておられるとのことでした。
最終日の懇親会でもたくさんの方とお話しすることができました。 お話しさせていただいた方にはOpenDoorの紹介をさせていただきました。 LayerXではOpenDoorという制度を設けており、OpenDoorを開いている弊社メンバーとカジュアルに面談してお話しすることができるようになっております。 こうしたイベントの懇親会以外でも一対一でお話ができますので、ぜひOpenDoorのページをご覧いただき、気になったテーマを掲載しているメンバーとお話ししてみてください!
また、弊社製品のバクラク申請・経費精算の紹介もさせていただきました。 こちらのモバイルアプリはFlutterでできております! アプリの内情や知見については弊ブログでも書いておりますので、ぜひ読んでみてください。
最後まで熱量たっぷりの楽しいイベントでした! 開催してくださったスタッフの皆様、ありがとうございます!
Thank you so much!! #FlutterNinjas pic.twitter.com/tDm4K7Li6a
— FlutterNinjas Tokyo (@FlutterNinjas) 2025年5月31日
id:kikuchy が所属しているFintech事業部 / 三井物産デジタル・アセットマネジメントでは、個人向け資産運用サービス「ALTERNA(オルタナ)」のモバイルアプリの開発を計画しています。 まだどんなアーキテクチャにするかは未定です。Flutterを使うかもしれませんし、使わないかもしれません。 しかし勘所は大体のクロスプラットフォームフレームワークで共通であることが多いですから、今回得た知識を活かして良いアプリにしていきたいと考えています。
そして、一緒に開発できるエンジニアの仲間を探しています! 現在は、生成AIを用いた業務効率化をやってみたい方を特に募集中です。 ピンときたらぜひご応募ください!