Dart
イベント
該当するコンテンツが見つかりませんでした
マガジン
該当するコンテンツが見つかりませんでした
技術ブログ
Flutter3.38アップグレードにおけるiOSとAndroidの影響範囲 背景 Flutter3.38アップグレードの手順 パッケージのバージョン依存関係調整 依存関係の解消によって副次的問題が発生 1. Dart SDK バージョン 2. Ferryエコシステム(GraphQLクライアント) 3. Freezed(コード生成) 4. Firebase(iOS 13対応のため2.x系を使用) 5. その他の重要な更新 6. Isar Plus(データベース)モデル修正 解決した依存関係の競合 競合1: isar_db_generator 競合2: intl バージョン 競合3: source_gen バージョン 競合4: build バージョン 競合5: gql_exec バージョン 競合6: ferry バージョン 競合7: web パッケージ(iOS 13対応のための調整) 競合8: Firebase iOS 15要件 参考リンク 既存コードの改修作業 1. isar_plus 移行に伴うimport文の変更 2. isar_plus 移行に伴うPodfileの変更 3. NDKバージョンの明示的指定 4. Android app の namespace(AGP 8.x 必須) 5. サブプロジェクトへの namespace 注入 6. BuildConfig の有効化 7. Freezed 3.x マイグレーション(全モデルに abstract 修飾子) 8. retrofit / ParseErrorLogger 対応 9. Android 旧埋め込み (PluginRegistry.Registrar) 削除対応 10. iOS CocoaPods更新 Flutter バージョン別 カート追加時パフォーマンス比較レポート 比較サマリー 結論 主な改善要因(推測) 今後の検討 まとめ 1. テスト 2. iOS 11-12ユーザーへの対応検討 最後に こんにちは、開発本部 開発2部 RetailHUB NetSuperグループに所属するホーク🦅アイ👁️です。 背景 現在提供しているネットスーパーアプリはFlutter+Dartで実装しております。一方で、昨年2025年11月1日までに対応が必要であったGoogleからの メモリの16KBページサイズをサポートせよ という通知を延長申請して2026年5月31日まで対応を保留にしていました。2026年2月現在、この延長期限も近づいてきていることを理由にFlutterのバージョンを3.38系にアップグレードすることになりました( こちら の公式ブログにも3.38から標準対応したとあります)。 Flutter3.38アップグレードの手順 通常、Flutterのバージョンをアップグレードする際の流れとしては、以下の2点を気にする必要があり実際にそのプロセスを踏まないといけないことも少なからずあります。 パッケージ依存関係の解消 既存ソースコードで改修 今回、対象のソースコードで利用しているFlutterバージョンは3.24.1と古めのバージョンであるためバージョン差分が大きく、2点とも対応が発生しました。以下にその2点の対応について詳細を記していきます。 パッケージのバージョン依存関係調整 目的はあくまでAndroidアプリの16KBページサイズに対応することなのでAndroidアプリのビルドをまず意識した以下のバージョンを調整しました。 Flutter,Dartのバージョンを上げる Flutter3.38.9、Dart3.10.8にしました DevTools 2.51.1 Gradleのバージョンを上げる 8.7にしました AGPのバージョンを上げる 8.5.1にしました Kotlinのバージョンを上げる 2.0.21にしました NDKバージョンを明示指定 29.0.14206865にしました その他利用ライブラリの対応バージョンをtrial and errorで上げる 現状のバージョンのままでビルドしてみてエラーが出たら上げるを繰り返しました 依存関係の解消によって副次的問題が発生 今回、Androidアプリのためにアップグレードをするので必要なライブラリパッケージも必要最低限のものだけを最小限でアップグレードすることを心がけたのですが、意図せずiPhoneアプリ側の方にも影響を及ぼしてしまうことが判明しました。具体的には以下のことが発生しました。 iOSの最小メジャーバージョン番号が12から13以上に引き上げ 直接的な引き上げ条件は、 Flutter公式 によれば、swiftコードを利用する場合とありますがFlutter3.38自体がそれに該当するということ( 参考ページ )でした。というわけで、必然的にFlutter3.38にしないといけない場合はiOS最小対応バージョンも13以上になるということでした。 最終的には以下に挙げるバージョン対応で一旦、すべての依存関係の競合を解決し、 pub get 、コード生成、iOS CocoaPodsインストールがすべて成功しました。 1. Dart SDK バージョン 変更 : >=3.7.0 <4.0.0 → >=3.8.0 <4.0.0 理由 : json_serializable と freezed の最新版が要求 2. Ferryエコシステム(GraphQLクライアント) パッケージ 最終バージョン 理由 ferry ^0.16.1 ferry_generator 0.12.0+3との互換性 ferry_generator ^0.12.0+3 build 4.0対応 build_runner ^2.10.3 build 4.0対応 gql_code_builder_serializers ^0.1.0 ferry_generator 0.12.0+で必須 gql_exec ^1.0.0 ferry_generator依存関係 gql_http_link ^1.0.0 gql_execとの互換性 gql_transform_link ^1.0.0 gql_execとの互換性 3. Freezed(コード生成) パッケージ 最終バージョン 理由 freezed ^3.2.5 build 4.0対応 freezed_annotation ^3.0.0 freezed 3.x対応 4. Firebase(iOS 13対応のため2.x系を使用) パッケージ 最終バージョン 理由 firebase_core ^2.32.0 iOS 13サポート(3.x+はiOS 13必須) firebase_analytics ^10.10.7 firebase_core 2.x互換 firebase_crashlytics ^3.5.7 firebase_core 2.x互換 firebase_messaging ^14.7.10 firebase_core 2.x互換 & webパッケージ互換 firebase_remote_config ^4.4.7 firebase_core 2.x互換 firebase_app_installations ^0.2.5+7 firebase_core 2.x互換 Firebase iOS SDK : 10.25.0(iOS 13+をサポート) 5. その他の重要な更新 パッケージ 最終バージョン 理由 intl ^0.20.2 flutter_localizations要求 retrofit_generator ^10.2.1 source_gen 4.0対応 json_annotation ^4.9.0 json_serializable要求(dependenciesに追加) 6. Isar Plus(データベース)モデル修正 isar_plus v4のAPI変更に対応: 変更後(isar_plus v4スタイル): @collection class EventLog { EventLog({required this .id}); final int id; // Auto-increment id (isar_plus v4) late String data; } 主な変更点: @Collection() (大文字)→ @collection (小文字) Id id = Isar.autoIncrement → final int id とコンストラクタで受け取る 実際のauto-increment IDは isar.collection.autoIncrement() で生成 解決した依存関係の競合 競合1: isar_db_generator 問題 : isar_db_generator パッケージが存在しない 解決 : isar_db は元の isar_generator を使用することを確認 競合2: intl バージョン 問題 : flutter_localizations が intl 0.20.2 を要求 解決 : intl を ^0.20.2 に更新 競合3: source_gen バージョン 問題 : isar_plus が source_gen ^4.0.2 を要求、 retrofit_generator ^8.1.0 が source_gen ^1.3.0 を要求 解決 : retrofit_generator を ^10.2.1 に更新(source_gen 4.0対応版) 競合4: build バージョン 問題 : build_runner >=2.9.0 が build ^4.0.0 を要求、 freezed ^2.x が build ^2.3.1 を要求 解決 : freezed を ^3.2.5 に更新(build 4.0対応版) 競合5: gql_exec バージョン 問題 : gql_transform_link が古い gql_exec を要求、 ferry_generator 0.12.0+3 が gql_exec ^1.0.0 を要求 解決 : gql_exec 、 gql_http_link 、 gql_transform_link をすべて1.x系に更新 競合6: ferry バージョン 問題 : ferry ^0.14.2+1 が ferry_exec ^0.3.1 を要求、 ferry_generator 0.12.0+3 が ferry_exec ^0.7.0 を要求 解決 : ferry を ^0.16.1 に更新 競合7: web パッケージ(iOS 13対応のための調整) 問題 : isar_plus が web ^1.1.0 を要求、Firebase 4.x系が web ^0.5.1 を要求 解決 : Firebaseパッケージを2.x系にダウングレード(iOS 13サポートのため) 競合8: Firebase iOS 15要件 問題 : Firebase 4.x系(firebase_core 4.0+)はiOS 15を最小要件とする 解決 : Firebase 2.x系(firebase_core 2.32.0)を使用してiOS 13をサポート 参考リンク isar_plus v4 ドキュメント ferry_generator changelog freezed 3.0 migration Firebase Flutter changelog firebase_core 3.0.0 breaking changes 既存コードの改修作業 前述にある依存パッケージライブラリをアップグレードすることで破壊的変更が発生してしまった全箇所をエラーがなくなるまで対応していくという作業も相当数発生しました。 1. isar_plus 移行に伴うimport文の変更 package:isar/isar.dart → package:isar_plus/isar_plus.dart に変更 2. isar_plus 移行に伴うPodfileの変更 ios/Podfile で isar_flutter_libs → isar_plus_flutter_libs に変更 3. NDKバージョンの明示的指定 追加 : ndkVersion "29.0.14206865" (安定版最新。r28+ で 16KB アライメント対応のため r29 を使用) ファイル : app/build.gradle 理由 : NDK r28以上で16KBアライメントがデフォルト対応。固定していた 28.0.12674087 ではなく、安定版最新 29.0.14206865 を推奨 4. Android app の namespace(AGP 8.x 必須) 追加 : namespace "tv.every.fresh" ファイル : app/build.gradle 理由 : AGP 8.x ではモジュールに namespace の指定が必須。未指定だと「Namespace not specified」でビルド失敗する。 5. サブプロジェクトへの namespace 注入 追加 : Android library プラグインで namespace 未指定のサブプロジェクトに、 AndroidManifest.xml の package を namespace として設定 ファイル : build.gradle (root) 理由 : AGP 8.x では全モジュールに namespace 必須。古いパッケージは namespace 未指定のため「Namespace not specified」でビルド失敗する。pub cache は編集しないため、root の subprojects.plugins.withId("com.android.library") で manifest の package を注入する。 6. BuildConfig の有効化 追加 : 全 Android サブプロジェクトで buildFeatures.buildConfig true ファイル : build.gradle (root) 理由 : AGP 8.x では BuildConfig がデフォルト無効。custom BuildConfig を使うパッケージがあったため「defaultConfig contains custom BuildConfig fields, but the feature is disabled」でビルド失敗する。root の subprojects.afterEvaluate で全モジュールに有効化する。 7. Freezed 3.x マイグレーション(全モデルに abstract 修飾子) 対象 : @freezed を付けた全てのモデルクラス 対応 : Freezed 3.0 マイグレーションガイドに従い、 全てのクラス定義に abstract 修飾子を追加 変更例 : // 変更前 @freezed class Shop with _$Shop {...} // 変更後 @freezed abstract class Shop with _$Shop {...} 理由 : Dart 3.10 コンパイラ下で non_abstract_class_inherits_abstract_member エラーを解消するため。Freezed 3.x の生成コード(mixin の抽象メンバー)と互換させるには、公開クラスを abstract class にすることが必要。 実施方法 : 上記のとおり、該当する全モデルファイルで class → abstract class に手動で置換。 検証 : 本対応後に iOSビルド成功し、iOS Simulator(26.2)でアプリ起動を確認済。 8. retrofit / ParseErrorLogger 対応 対象 : retrofit パッケージをimportしているREST APIを実装したdartファイル(ex. rest_api.dart) 現象 : 旧 retrofit 4.1.0 + retrofit_generator 10.2.1 で生成したコードが型 ParseErrorLogger を参照するが、 package:retrofit/http.dart のみの import では参照できずコンパイルエラーになる 対応 : retrofit : ^4.1.0 → ^4.9.2 に更新(Dart 3.8 対応バージョン、ParseErrorLogger は package:retrofit/retrofit.dart で提供) rest_api.dart : import 'package:retrofit/retrofit.dart'; を追加し、生成コード(part ファイル)から ParseErrorLogger を参照可能にする。 package:retrofit/http.dart は retrofit.dart に含まれるため削除可 結果 : build_runner 再生成後も手動修正不要でビルド可能 9. Android 旧埋め込み (PluginRegistry.Registrar) 削除対応 Flutter 3.38 では v1 Android 埋め込み API( PluginRegistry.Registrar / registerWith )が削除されている。以下のパッケージを更新済み。 path_provider : ^2.1.3 → ^2.1.5 (path_provider_android 2.2.5+ を要求し、v1 削除済み) shared_preferences : ^2.2.3 → ^2.3.4 (shared_preferences_android 2.2.3+ で v1 削除済み) url_launcher_android : ^6.0.38 → >=6.3.3 <6.3.27 (6.3.3 で v1 削除。6.3.27+ は androidx.browser 1.9.0 が AGP 8.9.1 を要求するため 6.3.26 以下に制限) compileSdkVersion : 34 → 36(path_provider_android 等が SDK 36 を要求。 app/build.gradle ) 10. iOS CocoaPods更新 iOS最小デプロイメントターゲットをiOS 13.0にFixしました。 platform :ios , ' 13.0 ' config.build_settings[ ' IPHONEOS_DEPLOYMENT_TARGET ' ] = ' 13.0 ' Flutter バージョン別 カート追加時パフォーマンス比較レポート 新しいバージョンになったのでそれだけでどれだけ既存アプリのパフォーマンスにも影響を及ぼしたか気になったのでFlutter DevToolsでプロファイリングしてTimeline Eventsを3.24.1と3.38.9でベンチマーク比較してみました。 以下は、 同じカート追加アクション で取得したDevToolsの計測データを用い、 Flutter 3.24.1 と Flutter 3.38.9 のパフォーマンスを比較したレポートです。 項目 Flutter 3.24.1 Flutter 3.38.9 総フレーム数 96 107 比較サマリー 指標 Flutter 3.24.1 Flutter 3.38.9 差分 傾向 平均FPS 19.8 fps 48.3 fps +28.5 fps ✅ 大幅改善 平均フレーム時間 50.47 ms 20.71 ms -29.76 ms ✅ 約59%短縮 平均ビルド時間 7.23 ms 1.25 ms -5.98 ms ✅ 約83%短縮 平均ラスター時間 26.86 ms 15.32 ms -11.54 ms ✅ 約43%短縮 平均Vsyncオーバーヘッド 5.96 ms 1.46 ms -4.50 ms ✅ 約75%短縮 最大フレーム時間 274.89 ms 85.51 ms -189.38 ms ✅ 約69%短縮 最大ビルド時間 115.16 ms 18.66 ms -96.50 ms ✅ 約84%短縮 最大ラスター時間 145.56 ms 41.46 ms -104.10 ms ✅ 約72%短縮 Janky率 100.0% 88.8% -11.2pt ✅ 改善 重度Jank率 (>33ms) 38.5% 4.7% -33.8pt ✅ 大幅改善 結論 Flutter 3.38.9 は 3.24.1 と比較して、カート追加時のパフォーマンスが全体的に大きく改善しています。 平均FPSが 19.8 → 48.3 と約2.4倍になり、体感の滑らかさが向上しています。 ビルド時間・ラスター時間・Vsyncオーバーヘッドのいずれも短縮。 最大フレーム時間は 274.89ms → 85.51ms(約69%短縮) と、改善が確認できます。 重度Jank率は 38.5% → 4.7% と約1/8に減少。 主な改善要因(推測) Flutterエンジン・Skiaの最適化 ビルドパイプラインの効率化(ビルド時間の大幅短縮) Vsyncまわりのオーバーヘッド低減 今後の検討 3.38.9 時点でも Janky率 88.8%、平均FPS 48.3 であり、60fps目標にはまだ余裕があります。 ラスターが主なボトルネックのため、画像最適化・RepaintBoundary・Clip削減などの施策を続けると、さらに改善の余地があります。 まとめ 本ブログでは、Android15以降でサポートされている16KBページサイズに対応するためFlutterのバージョンを3.38系にアップグレードすると既存アプリにどのような影響を及ぼすことになるかについてお話ししました。 一旦は、両OSともビルドが成功してアプリ起動までは確認が取れたのでこれから5月31日まであまり日がないですが以下のようなThe next stepsに基づいて進めていく予定であることをお知らせして結びとさせていただきます。 1. テスト 単体テストの実行 統合テストの実行 手動テスト(特にデータベース操作とGraphQL操作) 2. iOS 11-12ユーザーへの対応検討 アプリストアで古いバージョンを継続提供 ユーザーへの事前通知 段階的な移行計画 最後に エブリーでは、ともに働く仲間を募集しています。 テックブログを読んで少しでもエブリーに興味を持っていただけた方は、ぜひ一度カジュアル面談にお越しください! corp.every.tv
目次 はじめに 抱えていた課題 解決策: スキーマ駆動開発の導入 カスタムプラグインの実装 運用のフ ...
はじめに iOSDC Japan 2025とは 印象に残ったセッション ユーザー数10万人規模のアプリで挑んだトップ画面のUI刷新 ABEMAモバイルアプリがKotlin Multiplatformと歩んだ5年 ─ 導入と運用、成功と課題 iOSエンジニアキャリア設計入門 〜”先進性”をキャリアの武器へ〜 カスタムUIを作る覚悟 イベントの雰囲気 まとめ はじめに こんにちは!LIFULL HOME’S iOSアプリエンジニアの遠藤・佐藤です。 今回は、2025年の9月19日(金) 〜 9月21日(日)の3日間で開催された、iOSに関連した技術をコアテーマにしたテックカンファレンス「iOSDC Japan 2025」に参加してきました。この記事では、3日間で行われたセッションの中から私たちの印象に残ったセッションやイベントの様子について振り返ります。 iOSDC Japan 2025とは iOSDCは、記念すべき第10回目の開催を迎えました!これまでは早稲田大学理工学部 西早稲田キャンパスにて開催されていましたが、第10回となる今回は会場がグレードアップし、有明セントラルタワーホール&カンファレンスにて開催されました。トークテーマはiOSに関する内容を始め、Vision Proやクロスプラットフォーム、AIといった多岐にわたる分野を網羅し、LT大会や多数の企画も充実していました。 iOSDC Japan 2025の公式サイトはこちら iosdc.jp トーク動画の視聴はこちら www.youtube.com 印象に残ったセッション ユーザー数10万人規模のアプリで挑んだトップ画面のUI刷新 speakerdeck.com この発表では、ユーザー数10万人超のアプリにおいて、WebViewベースであったトップ画面をネイティブ実装に刷新した事例が紹介されていました。従来の操作感を損なわずに段階的に移行を進めたプロジェクトで、多くのユーザーを抱えるアプリのUI刷新の事例として非常に参考になる内容でした。 特に印象的だったのは、ユーザー体験を最優先にした移行戦略です。段階的な移行を進める中で、各フェーズごとにユーザーからのフィードバックを収集し、課題を一つずつ解決していったそうです。具体的な指標として「ロールバック率(新画面から旧画面に戻したユーザーの割合)」を計測し、改善を重ねていった点が紹介されていました。 こういったフィードバック収集と改善の結果、最終的にロールバック率5%未満という高い受け入れ率も記録しつつ移行を完遂されており、ユーザーとの対話を徹底したUI刷新の成功事例として、とても勉強になりました。(遠藤) ABEMAモバイルアプリがKotlin Multiplatformと歩んだ5年 ─ 導入と運用、成功と課題 speakerdeck.com こちらの発表では、ABEMAにおいて約5年間にわたってKMP(Kotlin Multiplatform)を運用してきた具体的な事例を紹介されており、実際に業務でKMPを扱う私にとって、とても興味深い発表でした。 2020年ごろから検証を開始し、段階的に導入を進めてきた経緯を詳しく説明して下さっていました。現在では、サービスの中心となる画面に関連するロジックの多くがKMPによって共通化されているとのことで、大規模サービスでの長期運用がどのように実現されているのか、その実態を知ることができました。 また、KMPの導入プロセスや実際に生じた課題、そしてチームでの実装効率がどう変化したかなど、実践的な内容が取り上げられていました。特に、処理をどこまで共通化すべきかという判断基準や、Swift6やSwiftUIの導入とKMPをどう両立させたかなど、現場で直面する具体的な課題への取り組みを紹介されていて、多くの学びを得ることができました。(遠藤) iOSエンジニアキャリア設計入門 〜”先進性”をキャリアの武器へ〜 speakerdeck.com このセッションでは、ネイティブアプリエンジニアを取り巻く最新の市場動向を知ることができました。スマートフォンアプリ開発全体では、クロスプラットフォームであるFlutter(Dart)の勢いが増しており、SwiftとFlutterの両方を使うエンジニアも増加しているという明確なトレンドを解説してくださいました。 AIの活用によって開発効率は急速に向上していますが、企業側からのニーズは引き続き高い水準を保っているそうです。 今後のキャリア戦略としては、iOSとAndroidの両OSのネイティブ知識に加え、共通化の判断ができる能力がより重要になると感じました。 ちなみに、弊社のLIFULL HOME’Sアプリでも、Kotlin Multiplatformを使ってバックエンドの共通化を行い、ネイティブの特性を活かしつつ開発効率の向上に取り組んでいます。詳細については、過去の記事( LIFULL における Kotlin Multiplatform(KMP) - LIFULL Creators Blog )でご紹介していますので、ぜひご覧ください!(佐藤) www.lifull.blog カスタムUIを作る覚悟 speakerdeck.com カスタムUIは、標準UIが持つアクセシビリティや多様な入力への対応を、すべて自力で担う必要があるという、そのコストと難しさを改めて痛感させられる内容でした。 iOS/iPadOSアプリ開発における基本的な考え方は、標準APIを最大限に活用することです。安易にナビゲーションやコントロールをカスタム化してしまうと、ユーザー体験を損なうリスクがあることを認識しておく必要があります。カスタムUIを選択するということは、単に実装する技術的な問題ではなく、UIデザイナーとエンジニアが静的なデザインを超えて密に連携すること、そして時には勇気ある撤退も視野に入れるという「覚悟」が不可欠だと学びました。 後日、このセッションの動画をエンジニアだけでなく、企画職やデザイナー職も交えて視聴し、それぞれの視点からの学びを共有しました。カスタムUIの選択が、プラットフォームへの深い理解、UX、そしてチーム全体の総合的な判断に関わる重要な問題であるという認識を、チーム全体で共有できたことは非常に貴重な機会となりました。(佐藤) イベントの雰囲気 ルーキーズLTでは会場全体が登壇者の好きな色にサイリウムの色を切り替えて、応援していました!一人一人に合わせた応援で登壇者を後押しする、温かい演出が印象的でした! サイリウムを振ってLT発表者を応援📣 会場の1フロアほぼ全体にスポンサー企業ブースが立ち並び、各社の技術紹介やノベルティ配布、クイズなどで大盛況でした🥳 ビンゴ形式のスタンプラリーで各社のブースを巡る企画もあり、楽しみながら企業の取り組みを知ることができる工夫が印象的でした! スポンサー企業ブース1 スポンサー企業ブース2 ちなみにday1、day2ともに、朝にドーナツが配られていました〜🍩 会場が変わっても、早朝から用意してくださった運営の皆さんの熱量と気配りに感謝です! 4Fの展示ルーム前にドーナツがデプロイされました! 是非ご賞味ください 🍩 #iosdc pic.twitter.com/ulEsr2t0Wo — iOSDC Japan (@iosdcjp) 2025年9月21日 まとめ 今回iOSDCに参加して、様々なセッションを通じて、各社の取り組みや技術選定の背景など、日頃の開発現場の姿を垣間見ることができました。 また、昨今はFlutterやKotlin Multiplatformをはじめとしたマルチプラットフォーム開発が活発であったり、比較的新しいアーキテクチャを取り入れる事例も見受けられるなど、モバイルアプリ開発が依然として目まぐるしく変化していることを改めて実感しました。 弊社のアプリチームでも実際にSwiftUI、Kotlin Multiplatformを取り入れた開発をメインで行っていることもあるので、今回得た視点、知見を日頃の開発業務にぜひ活かしていこうと思います。 最後に、LIFULLでは一緒に働いていただける仲間を募集しています。単にサービス開発をするだけでなく、自らの知見を深め、エンジニアやプロダクトマネージャーとしてのキャリアを築く上で大切な事を得る機会が多くある職場です。カジュアル面談も実施しておりますので、もし興味があればそちらもご覧いただければと思います。 hrmos.co hrmos.co hrmos.co
動画
該当するコンテンツが見つかりませんでした











