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.2k
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
730
iosdc_2018.pdf
kyoheig3
2
3.3k
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
[2026-10-14](C)Re:ゼロから始める異世界生活〜始まりの終わりと終わりの始まり〜
tosite
0
140
Kotlinの15年とServer-Side Kotlin
n_takehata
1
160
Web Framework Benchmark Battle 2026, Any%
a_matsuda
2
2.7k
AI-Powered Domain-Driven Design
ziobrando
0
240
ジョジョの世界をXRで再現する
mofurune
0
180
🇪🇸 React Alicante 2026 (Workshop)
ythecombinator
PRO
0
100
気持ちぃ〜角丸 Squircle
ryu1013
0
330
Zero-Tap Sign-In対応、結局何をすればいいの?
mitohato14
0
320
あなたの await、OS まで届いてる? strace で覗く JavaScript の非同期
hasutosasaki
1
950
Kotlinize Is Not Just Converting to Kotlin
chigichan24
1
180
RAG の “R” を Swift で覗いてみる 〜「意味から探す」検索の仕組み〜
nao_randd
0
170
Atomic Design, Enforced: Scaling Mobile Design Systems (next.app devCon / droidCon Berlin 2026)
steliosf
PRO
0
180
Featured
See All Featured
So, you think you're a good person
axbom
PRO
2
2.2k
Why You Should Never Use an ORM
jnunemaker
PRO
61
10k
Building the Perfect Custom Keyboard
takai
2
910
What the history of the web can teach us about the future of AI
inesmontani
PRO
2
750
Let's Do A Bunch of Simple Stuff to Make Websites Faster
chriscoyier
508
140k
brightonSEO & MeasureFest 2025 - Winning Strategies for Black Friday CRO & PPC - Christian Goodrich
cargoodrich
3
870
Tips & Tricks on How to Get Your First Job In Tech
honzajavorek
1
810
Everyday Curiosity
cassininazir
0
360
jQuery: Nuts, Bolts and Bling
dougneiner
66
8.6k
Hiding What from Whom? A Critical Review of the History of Programming languages for Music
tomoyanonymous
3
1.4k
Rebuilding a faster, lazier Slack
samanthasiow
85
9.7k
The World Runs on Bad Software
bkeepers
PRO
72
12k
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 !