Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
layerx_20241129.pdf
Search
Sponsored
·
Your Podcast. Everywhere. Effortlessly.
Share. Educate. Inspire. Entertain. You do you. We'll handle the rest.
→
Kyohei Ito
November 29, 2024
Programming
530
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
1.9k
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
940
ca.swift_2.pdf
kyoheig3
9
1.4k
Other Decks in Programming
See All in Programming
PyConJP2026_wat_Python × Signal Processing: How to Draw Pictures with Sound Using Spectrogram Art
wat
0
590
Oxlintはいいぞ(続)
yug1224
1
490
AWS Transform Customによる Spring Boot 2.xから4.xへのVerUp
satoshi256kbyte
2
110
まずはプロンプトガイドを読もう、話はそれからだ
kiakiraki
1
240
komatsuna「分散システムにおけるバグ分析手法」
komatsunaqa
0
290
go-spidermonkeyでAIエージェントのCode Modeを実装する
syumai
3
1.4k
30年振りにコンパイラの定数整数除算を改善した
herumi
9
4.3k
信頼性の目標を誰も求めてない
shubox
0
400
レビュー履歴をAIに食わせて、 Compose移行を加速するs
shihochan
0
240
Go 1.27からのGODEBUG / Go 1.27 リリースパーティ #go127party
mazrean
0
260
まだ間に合う!今年の夏こそSchemeのマクロ展開器を完全理解!
omasanori
0
580
freee が目指す データ マネジメント戦略 AI-Ready 時代を支える 攻めのガバナンスとは
freee
PRO
0
530
Featured
See All Featured
WCS-LA-2024
lcolladotor
0
810
Optimising Largest Contentful Paint
csswizardry
37
3.9k
The Pragmatic Product Professional
lauravandoore
37
7.4k
Paper Plane
katiecoart
PRO
2
53k
Joys of Absence: A Defence of Solitary Play
codingconduct
1
450
The Language of Interfaces
destraynor
162
27k
What the history of the web can teach us about the future of AI
inesmontani
PRO
1
670
Designing Experiences People Love
moore
143
24k
The Invisible Side of Design
smashingmag
301
52k
I Don’t Have Time: Getting Over the Fear to Launch Your Podcast
jcasabona
35
2.8k
How to Build an AI Search Optimization Roadmap - Criteria and Steps to Take #SEOIRL
aleyda
1
2.2k
How to Grow Your eCommerce with AI & Automation
katarinadahlin
PRO
1
250
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 !