Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
layerx_20241129.pdf
Search
Sponsored
·
SiteGround - Reliable hosting with speed, security, and support you can count on.
→
Kyohei Ito
November 29, 2024
Programming
540
2
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
layerx_20241129.pdf
Kyohei Ito
November 29, 2024
More Decks by Kyohei Ito
See All by Kyohei Ito
flutter_kaigi_2025.pdf
kyoheig3
2
1.1k
flutterkaigi_2024.pdf
kyoheig3
0
2k
flutter_kaigi_2021.pdf
kyoheig3
0
1.2k
flutter_kmm_1.pdf
kyoheig3
1
1.2k
ca.swift_10.pdf
kyoheig3
0
720
iosdc_2018.pdf
kyoheig3
2
3.2k
orecon_vol1.pdf
kyoheig3
4
1.8k
iosdc_2017.pdf
kyoheig3
4
950
ca.swift_2.pdf
kyoheig3
9
1.4k
Other Decks in Programming
See All in Programming
Starting & Sustaining Code-Based E2E Testing for Non-Coding QA Teams( #jasstniigata )
teyamagu
PRO
1
820
GitHubハンズオン講座 — 実務レベルのチーム開発のフローを身につけよう
junhat6
0
110
Unity6 URPによる海底をテーマにしたVJシステムの解説 | Unity Shader 完全に理解した 勉強会
gam0022
0
260
すこし踏み込む CancellationToken
htkym
2
1.5k
Findy - エンジニア向け会社紹介/Findy Company Deck
findyinc
6
400k
Heart of Swift Concurrency
koher
0
1.1k
マイコン向けの軽量Ruby「PicoRuby」で各種デバイスを制御するネイティブアプリの実現手法
bash0c7
0
470
AHC070解法紹介
eijirou
0
150
Go × SIMDで高速化するベクトル検索 ~ルーフラインモデルでSIMDが効く境界を探れ! ~
po3rin
1
5.7k
世界の中心で、AI(App Intents)をさけぶ ー App Intents中心設計の実践ガイド
touyou
0
750
速く作れる。その次は、速く確かめられる開発へ 〜AIネイティブ開発を支える、Shift Down〜 / Can build fast. Next, moving to development where we can verify fast.
rkaga
8
5.3k
スマートフォンでモールス信号を送受信する 〜スマートフォンのLEDとカメラで作る光通信の設計と実装〜
atsuki_seo
0
220
Featured
See All Featured
Statistics for Hackers
jakevdp
799
230k
Context Engineering - Making Every Token Count
addyosmani
9
1.2k
実際に使うSQLの書き方 徹底解説 / pgcon21j-tutorial
soudai
PRO
203
76k
Digital Ethics as a Driver of Design Innovation
axbom
PRO
1
440
A Modern Web Designer's Workflow
chriscoyier
699
190k
[Rails World 2023 - Day 1 Closing Keynote] - The Magic of Rails
eileencodes
38
3k
Color Theory Basics | Prateek | Gurzu
gurzu
1
480
We Have a Design System, Now What?
morganepeng
55
8.3k
Producing Creativity
orderedlist
PRO
348
41k
sira's awesome portfolio website redesign presentation
elsirapls
0
430
Redefining SEO in the New Era of Traffic Generation
szymonslowik
1
450
Navigating Team Friction
lara
192
16k
Transcript
UI ίϯϙʔωϯτ͔Βߟ͑Δ ΞʔΩςΫνϟ Flutter ΞʔΩςΫνϟઃܭͷ࠷લઢ
About Me ҏ౻ ګฏ גࣜձࣾαΠόʔΤʔδΣϯτ Github: KyoheiG3 X: KyoheiG3
MVVM BLoC Redux MVC Flux Provider
MVVM BLoC Redux MVC Flux Provider
Flutter ެࣜυΩϡϝϯτ https://docs. fl utter.dev/app-architecture
MVVM • Ͳ͏͍͏୯ҐͰׂΛ͚Δ͖͔ʁ
Service • ଓ͖͢σʔλιʔεͷ୯ҐͰଘࡏ͢Δ͜ͱ͕·͍͠
Repository • ΞϓϦͰѻ͏σʔλͷछྨ͝ͱʹ༻ҙ͢Δ
Data layer • σʔλσʔλιʔεͷ୯ҐͰׂΛ͚ͯѻ͏͜ͱ͕Ͱ͖ͦ͏
ViewModel • View 1ͭʹ͖ͭ ViewModel 1ͭʹͳΔ
View • Widget 1ͭʹ͖ͭ ViewModel 1ͭͰͳ͍ • ΞϓϦͷػೳʹରͯ͠ 1ͭଘࡏ͢Δʢʁʣ
UI layer • ΞϓϦͷػೳʹରͯ͠ 1ͭଘࡏ͢Δʢʁʣ
͓Βͤը໘ 1ը໘ʹ 1ػೳ
͓ؾʹೖΓҰཡը໘ ಉ͡ػೳͷཏྻ
ϗʔϜը໘ ༷ʑͳػೳͷू߹ମ
ϗʔϜը໘ UI layer UI ίϯϙʔωϯτ ͷ୯ҐͰ࡞Δ
Flutter ެࣜυΩϡϝϯτ https://docs. fl utter.dev/cookbook/ architecture/optimistic-state
Example feature: a subscribe button ը૾ग़లɿOptimistic State / https://docs. fl
utter.dev/cookbook/architecture/optimistic-state
FlutterKaigi 2024
FlutterKaigi 2024
ొਓ
্Ґͷ ViewModel ͕Լͷ ViewModel Λ࡞Δύλʔϯ
্Ґͷ ViewModel ͕Լͷ ViewModel Λ࡞Δύλʔϯ @riverpod Future<HomeViewModel> homeViewModel(HomeViewModelRef ref) async
{ final favorites = await ref.watch(favoriteListStateNotifierProvider.future); final notifications = await ref.watch(notificationListStateNotifierProvider.future); return HomeViewModel( favorite: HomeFavoriteViewModel(favorites: favorites), notification: HomeNotificationViewModel(notifications: notifications), ); }
্Ґͷ ViewModel ͕Լͷ ViewModel Λ࡞Δύλʔϯ class HomePage extends ConsumerWidget {
const HomePage({super.key}); @override Widget build(BuildContext context, WidgetRef ref) { final homeViewModel = ref.watch(homeViewModelProvider); return homeViewModel.when( data: (viewModel) { return Column( children: [ HomeFavoriteList(model: viewModel.favorite), HomeNotificationList(model: viewModel.notification), ], ); }, ); } }
ίϯϙʔωϯτຖʹ ViewModel Λ࡞Δύλʔϯ
ίϯϙʔωϯτຖʹ ViewModel Λ࡞Δύλʔϯ class HomeNotificationList extends ConsumerWidget { const HomeNotificationList({super.key});
@override Widget build(BuildContext context, WidgetRef ref) { final notificationListViewModel = ref.watch(notificationListViewModelProvider); return notificationListViewModel.when( data: (viewModel) { return Column( children: [ HomeNotificationItem(item: viewModel.notifications[0]), HomeNotificationItem(item: viewModel.notifications[1]), ], ); }, ); } }
ίϯϙʔωϯτຖʹ ViewModel Λ࡞Δύλʔϯ class HomeFavoriteList extends ConsumerWidget { const HomeFavoriteList({super.key});
@override Widget build(BuildContext context, WidgetRef ref) { final favoriteListViewModel = ref.watch(favoriteListViewModelProvider); return favoriteListViewModel.when( data: (viewModel) { return Column( children: [ HomeFavoriteItem(item: viewModel.favorites[0]), HomeFavoriteItem(item: viewModel.favorites[1]), ], ); }, ); } }
ίϯϙʔωϯτຖʹ ViewModel Λ࡞Δύλʔϯ class HomePage extends StatelessWidget { const HomePage({super.key});
@override Widget build(BuildContext context) { return const Column( children: [ HomeFavoriteList(), HomeNotificationList(), ], ); } }
Provider Λ্Ґʹ͑Δ
Provider Λ্Ґʹ͑Δ @riverpod Future<HomeFavoriteListViewModel> favoriteListViewModel(FavoriteListViewModelRef ref) async { final state
= await ref.watch(favoriteListStateNotifierProvider.future); return HomeFavoriteListViewModel( favorites: state.favorites, ); } @riverpod Future<HomeNotificationListViewModel> notificationListViewModel(NotificationListViewModelRef ref) async { final state = await ref.watch(notificationListStateNotifierProvider.future); return HomeNotificationListViewModel( notifications: state.notifications, ); }
@riverpod Future<HomeFavoriteListViewModel> favoriteListViewModel(FavoriteListViewModelRef ref) async { final state = await
ref.watch(favoriteListStateNotifierProvider.future); return HomeFavoriteListViewModel( favorites: state.favorites, ); } @riverpod Future<HomeNotificationListViewModel> notificationListViewModel(NotificationListViewModelRef ref) async { final state = await ref.watch(notificationListStateNotifierProvider.future); return HomeNotificationListViewModel( notifications: state.notifications, ); } favoriteListStateNotifierProvider.future notificationListStateNotifierProvider.future Provider Λ্Ґʹ͑Δ 4UBUFΛϦϑϨογϡ Ͱ͖Δͱྑͦ͞͏
Provider Λ্Ґʹ͑Δ class HomePage extends ConsumerWidget { const HomePage({super.key}); @override
Widget build(BuildContext context, WidgetRef ref) { return RefreshIndicator( onRefresh: () => ( ref.refresh(favoriteListStateNotifierProvider.future), ref.refresh(notificationListStateNotifierProvider.future), ).wait, child: const Column( children: [ HomeFavoriteList(), HomeNotificationList(), ], ), ); } }
ϗʔϜը໘ ௨৴ͦͷଞͷॲཧ͕ྃ ͨ͠ॱʹߋ৽͞Εͯ͠·͏
Provider Λ Override ͢Δύλʔϯ
Provider Λ Override ͢Δύλʔϯ @riverpod Future<NotificationListViewModel> homeNotificationListViewModel(_) => throw UnimplementedError();
class HomeNotificationList extends ConsumerWidget { const HomeNotificationList({super.key}); @override Widget build(BuildContext context, WidgetRef ref) { final notificationListViewModel = ref.watch(homeNotificationListViewModelProvider); return notificationListViewModel.when( data: (viewModel) { return Column( children: [ HomeNotificationItem(item: viewModel.notifications[0]), HomeNotificationItem(item: viewModel.notifications[1]), ], ); }, ); } }
Provider Λ Override ͢Δύλʔϯ @riverpod Future<FavoriteListViewModel> homeFavoriteListViewModel(_) => throw UnimplementedError();
class HomeFavoriteList extends ConsumerWidget { const HomeFavoriteList({super.key}); @override Widget build(BuildContext context, WidgetRef ref) { final favoriteListViewModel = ref.watch(homeFavoriteListViewModelProvider); return favoriteListViewModel.when( data: (viewModel) { return Column( children: [ HomeFavoriteItem(item: viewModel.favorites[0]), HomeFavoriteItem(item: viewModel.favorites[1]), ], ); }, ); } }
Provider Λ Override ͢Δύλʔϯ return FutureBuilder( future: ( ref.watch(favoriteListViewModelProvider.future), ref.watch(notificationListViewModelProvider.future),
).wait, builder: (context, snapshot) { final data = snapshot.data!; return ProviderScope( overrides: [ homeFavoriteListViewModelProvider.overrideWith((_) => data.$1), homeNotificationListViewModelProvider.overrideWith((_) => data.$2), ], child: const Column( children: [ HomeFavoriteList(), HomeNotificationList(), ], ), ); }, );
Provider Λ Override ͢Δύλʔϯ return FutureBuilder( future: ( ref.watch(favoriteListViewModelProvider.future), ref.watch(notificationListViewModelProvider.future),
).wait, builder: (context, snapshot) { final data = snapshot.data!; return ProviderScope( overrides: [ homeFavoriteListViewModelProvider.overrideWith((_) => data.$1), homeNotificationListViewModelProvider.overrideWith((_) => data.$2), ], child: const Column( children: [ HomeFavoriteList(), HomeNotificationList(), ], ), ); }, );
·ͱΊ • UI layer ΛͲͷΑ͏ͳ୯ҐͰ͚Δͷ͔Λߟ͑ͳ͕Βઃܭ͢Δ • View ಉ࢜Ͱ ViewModel ΛόέπϦϨʔ͠ͳ͍ํ๏ʹઓ͢Δ
• UI ͷίϯϙʔωϯτԽͷΈ͕Ͱ͖ͨΒɺෳࡶͰͳ͍ը໘ͰͳΔ ͘ಉ͡ΈΛར༻࣮ͨ͠ʹ͢Δ
Thanks !