VGV キーノート
最後のキーノートは VGV (Very Good Ventures) の CEO David DeRemer さん と Concepts Director Kyle Crouse さん によって行われました。 VGV は世界で最も有名な Flutter 企業の一つで、Google をはじめ数多くの企業と提携し、Flutter を使った高品質なアプリを開発してきました。

さらに、クライアントワークだけでなくオープンソースにも大きく貢献しており、very_good_cli や bloc ステート管理ライブラリなどのツールやパッケージを公開しています。 まさに Flutter を代表する企業であり、そんな彼らが最新プロダクトをこの場で紹介するのは自然な流れでした。

Multi-Device Maturity Model
現代の世界では、ユーザーは単に「プロダクトを使う」のではなく、複数のデバイスを横断したダイナミックな体験をしています。 スマートフォンやノートPCだけでなく、車載ディスプレイやキオスク端末に至るまで、それぞれのタッチポイントには 一貫性・パーソナライズ・コンテキスト認識 が求められます。
そこで私たちが開発したのが マルチデバイス成熟度モデル (Multi-Device Maturity Model, MDMM) です。 これはリサーチに基づいたフレームワークで、チームが現在のクロスプラットフォーム対応力を評価し、戦略的なギャップを見つけ、スケール可能で高品質な体験を提供するための明確なロードマップを描けるようにするものです。

ベネフィットと戦略的価値
MDMM を採用することで、組織全体に以下のような強力な成果をもたらします。
- 📈 市場投入までのスピード加速。開発プロセスを統合し、重複作業を排除することでサイクルを短縮。
- ⚙️ オペレーション効率の向上。クロスファンクショナルチームに共通ツールと効率化されたワークフローを提供。
- 🔗 スケーラブルな一貫性。デバイス、画面、環境に関わらず、統一感のある体験をユーザーに届けられる。
- 💡 顧客中心のエンゲージメント。文脈を理解したスマートな体験を実現し、リテンションやロイヤルティを高める。
- 🧭 戦略的な意思決定の高度化。 MDMM を使って現状を評価・ベンチマークし、マルチデバイス時代に持続的に成長できるロードマップを描く。
さらに彼らは今回の技術スタックについても紹介していました。というのも、ドライバーから送られてくるデータは 毎秒1000件以上のメッセージ という非常にハードな要件だったからです。
データ伝送には LiveKit を利用し、実際の表示部分には Flutter の Flame エンジン を採用。Flame は非常に高いパフォーマンスを誇るため、このように大量に流れ込むデータをリアルタイムに可視化するケースにおいて最適だったそうです。



Building a Full-Stack App for Apple Wallet Passes
今回のセッションでは、Apple WalletのパスをFlutterでフルスタック構築する方法 が紹介されました。例えばカンファレンスに参加するとき、カスタムのイベントパスをウォレットに追加できるようになります。その実装に使われたのが apple_passkit パッケージです。

開発フローとしてはまず API が必要 であり、ここで Dart Frog をバックエンドに採用していました。Dartでモデルを共有できる点は大きな利点です。また、アプリ全体の設計には Very Good Ventures が提唱する Very Good Layered Architecture を使用しているのも印象的でした。

次のステップとして、Wallet用の 識別子や証明書を作成 し、アプリからイベントパスのリクエストを送信します。このとき必要になるのが Team Identifier と Pass Identifier です。
リクエストを受け取ったバックエンド側では、まず未署名のパスを受信し、それを バックエンドで署名 します。さらにロゴやアイコン、パスのデータをサーバー側で設定する仕組みになっていました。
フロントエンド側では PKPassWidget を利用することで、実際にWalletアプリ内で表示されるパスをそのままプレビューできます。コード例も紹介されており、参考リポジトリはこちらです:
最後に、本題とは直接関係ありませんが、新しい dart_frog_lints パッケージについての紹介もありました。
RenderObject layer advantages without writing any RenderObjects
LeanCode の Albert Wolszon さんによる発表。期待していた通り、ハイクオリティでとても面白い内容でした。

普段はみんな当たり前のように Widget を使っていますが、Widget だけでは足りないケースに遭遇したことはありませんか?そのような時にRenderObject のレイヤーを活用すると、より柔軟にパフォーマンスの高い UI が作れます。
いつ使うのか?(代表的な例)
実際に RenderObject を意識するのはどんな場面か。Albert さんは2つの代表的な例を紹介していました。
- あるウィジェットのサイズを別のウィジェットに依存させたいとき→ 典型例が AppBar。アクションボタンのサイズに合わせてタイトルを中央に配置したいケースは、なんと 90% のユースケースを占めるそうです。

- あるウィジェットのサイズをビルダーに渡して使いたいとき → 例えば ListView に固定フッターを付けたい場合。フッターの高さを取得して、ListView に下 padding として反映させる、といった使い方です。

addPostFrameCallback + findRenderObject() というトリック

次に紹介されたのが「描画完了後にサイズを取得して反映させる」テクニックです。 addPostFrameCallback と findRenderObject() を組み合わせると実現できます。
ただし、これは正直「簡単だけど雑」な方法で、アルバートさん自身も「最も手抜きなやり方」と笑いながら解説していました 😂。計算のタイミングが明示的でないので、どのフレームで再計算されるのかがわかりづらい、という欠点があります。
RenderObject の世界
そこでより本格的なアプローチとして RenderObject のレイヤーに入っていきます。
- RenderObjectWidget + RenderBox → RenderObjectElement を自作し、3つのスロットを管理する形。柔軟ですがボイラープレートが多いです。
- SingleChildRenderObjectWidget / MultiChildRenderObjectWidget → RenderObjectWithChildMixin や ContainerRenderObjectMixin を組み合わせることで、コード量を減らしつつ RenderObject の強みを活かせます。
- SlottedMultiChildRenderObjectWidget + SlottedContainerRenderObjectMixin → カスタム Element を書かずに済み、ボイラープレートが大幅に削減されます。RenderObject の力をほぼそのまま使えるので、実用的かつ強力。
Boxy
最後に、アルバートさんが開発に関わっている Boxy パッケージを紹介してくれました。 Boxy を使えば、RenderObject をゼロから書くよりもはるかにシンプルにカスタムレイアウトを実現できます。コードもかなり短くなり、特にジュニアエンジニアが RenderObject に恐怖心を抱かないよう導入したとのこと。
実際のサンプルコードや資料はこちらで公開されています。 github.com
Lunch and AfterLunch activities
お昼ご飯はニョッキを食べました。ただ、日本で食べたニョッキと全然違っていてびっくり。こちらのはパスタというより、かなりジャガイモ感が強い味で、ちょっと不思議な感じでした。ドイツで最後にニョッキを食べたのがいつだったかも思い出せないくらい久しぶりですが、正直言うと日本の方が好みかもしれません。

再び Youseff Hain さんと
今回 Youseff さんに教えてもらった内容の中で特に参考になったのが、Objective-C のブロック(クロージャ)の扱いです。 たとえば HealthKit のウォーキングワークアウトを取得するようなコードを書くと、こんな感じになります👇
@override
Future<List<WalkingWorkout>> retrieveLastWalkingWorkouts({
int limit = 10,
}) async {
final workoutPredicate =
HKQuery.predicateForWorkoutsWithWorkoutActivityType_(
HKWorkoutActivityType.HKWorkoutActivityTypeWalking,
);
final sortDescriptor = NSSortDescriptor.sortDescriptorWithKey_ascending_(
hKSampleSortIdentifierEndDate,
false,
);
final sortDescriptors = NSArray.arrayWithObject_(sortDescriptor);
final handler = ObjCBlock_ffiVoid_HKSampleQuery_NSArray_NSError.listener(
(query, results, error) {
if (results != null) {
final workout = results.firstObject! as HKWorkout;
print('Workout found: $workout');
// retrieveRouteForWorkout(workout);
} else {
print('No workout found: ${error?.localizedDescription}');
}
},
);
final query = HKSampleQuery.new1()
.initWithSampleType_predicate_limit_sortDescriptors_resultsHandler_(
HKObjectType.workoutType(),
workoutPredicate,
1,
sortDescriptors,
handler,
);
health.executeQuery_(query);
// TODO: Get the actual data from the query
return [];
}
見ての通り、ObjCBlock_ffiVoid_HKSampleQuery_NSArray_NSError の部分がめちゃくちゃ長くて読みにくいですよね💦 Youseff さんのアドバイスは「typedef を使って別名を作る」ことでした。
たとえばこんな感じに typedef を定義しておくと…
typedef HKSampleQueryHandler = ObjCBlock_ffiVoid_HKSampleQuery_NSArray_NSError;
本体コードではこう書けるようになります👇
final handler = HKSampleQueryHandler.listener( (query, results, error) { // … }, );
これだけでだいぶスッキリ見やすくなります✨
さらに Kotlin 側から Android へクロージャを渡す話や、Android 固有のちょっとした癖についてもディープに議論。 最後には「Minecraft のプレイヤーは、ゲームを遊ぶために実は開発者向け最適化を理解している必要がある」という面白い例え話まで出てきて、すごく印象に残る時間でした。
Surviving the Long Game: Maintaining Flutter Apps Over Time

パネルディスカッション:長期プロジェクトのメンテナンス
途中からでしたが、長期的に運用する Flutter プロジェクトのメンテナンスについてのパネルディスカッションに参加しました。短い時間でもいくつか興味深いポイントが得られました。
まず議論に出たのは バージョンアップの扱い方。 安定版が出てもすぐに飛びつかず、慎重にアップデートしていくほうが安全だという意見がありました。特に大規模プロジェクトでは一気に上げるリスクが大きいとのこと。
また、コード生成ツールの使い方もテーマになっていました。 Simon さんは augment code を利用しており、他の参加者からは「build_runner をやめたほうがいい」という意見も。理由は大規模開発になるとどうしてもビルド時間や管理コストが高くつくためで、fromJSON のような単純処理は一度生成して固定するか、最近は AI に任せる選択肢もあると紹介されました。
さらに、途中で Flutter チームの Kevin Moore (Kevmoo) さんが加わり、とても実践的なアドバイスを共有してくれました。 多くの Flutter エンジニアが忘れがちなのが「Dart SDK 自体も定期的にアップデートすること」だそうです。そして新しい lint ルールを取り入れていくことも重要とのことでした。
こうした細かいメンテナンスポイントの積み重ねが、長期運用プロジェクトの安定性につながると改めて感じました。
After Event
3日目は少し早めに終了し、みんな一度ホテルに戻って休憩してから、Widgetbook 主催のアフターパーティーへ。 毎年恒例で、Widgetbook がビアガーデンを貸し切って最初の一杯をご馳走してくれます。🍻 雰囲気も最高で、さらに横にはテクノクラブもあって盛り上がりは抜群。

ビールが進むにつれて会話も弾み、みんなリラックスして冗談を言い合ったり、Flutterの話で盛り上がったりしていました。 途中で僕はなぜか Firebase のロゴどっちが好きかアンケートを始めてしまい(笑)、個人的には新しいロゴ派だったのですが、それは意外にも「少数派」だと思いきや…最終的には僕の意見が勝つ形に!
#ftcon25eu Apparently I am the only one thinking the newer on is better???
— Lucas Goldner | YOUTRUST の 金 瑠加須 💙 (@LucasGoldner) September 26, 2025
Poll who likes the new firebase logo better?
夜遅くなってからは、酔った勢いでFlutter ダジャレ大会に突入。英語のダジャレなので日本語だと伝わりにくいかもしれませんが、一応直訳も載せておきます。
- 「Hey, with that bad opinion, you should SizedBox.shrink out of here」
(そんな悪い意見言うなら、ここから SizedBox.shrink して消えたほうがいいよ!) - (みんなで回転木馬を押しているときに)
「Come on people, Navigator.of(context) push this!!!」
(さあみんな、Navigator.of(context).push でこれを押すんだ!) - 「Even if you come early to the airport, your flight could get Future.delayed」
(空港に早く着いたとしても、フライトは Future.delayed される可能性あるよ!)
くだらないダジャレですみません…😂
〆
今回の Fluttercon 2025 を通して、改めて イベントの力の大きさ を実感しました。こうした場は、単に新しい情報を得るだけでなく、自分の視野を広げ、他の開発者から直接学び、コラボレーションのきっかけを得る最高のチャンスです。正直に言うと、僕自身ここまでのキャリアを歩んでこられたのは、Fluttercon のようなイベントに参加してきたからだと心から思っています。もしあのとき、勇気を出して参加していなければ、今の僕はいませんでした。
もちろん、今の時代はほとんどの情報がオンラインで手に入りますし、資料やコードは誰でも閲覧できます。でも、人と直接話し、その人の苦労や成功談を聞くことで得られる刺激は、画面越しでは得られません。実際に会話することで、「そんなやり方があるのか」「自分もやってみよう」と思える瞬間が何度もありましたし、自分では絶対に調べなかったであろう分野にも挑戦するきっかけになりました。
もしこの記事を読んでいるあなたが、まだローカルのミートアップや勉強会に参加したことがないなら、ぜひ月に1回でも良いので試してみてください。Flutter に限らず、どの技術にも必ずコミュニティがありますし、参加してみるだけで大きな刺激が得られます。僕自身、Flutter Tokyo Meetup をおすすめしますが、それ以外の分野でも構いません。とにかく、自分のコンフォートゾーンを出ることが成長への第一歩です。勇気を出して一歩踏み出すことで、きっと新しい世界が見えてくるはずです。
