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
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
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
940
ca.swift_2.pdf
kyoheig3
9
1.4k
Other Decks in Programming
See All in Programming
thread_parallel_with_free-threaded_Python_and_NumPy.pdf
riku_sakamoto
0
350
モデルのリファクタリングが難しいと思ったら、そもそも複雑だったのはビジネス仕様だった ? / is-the-business-domain-the-real-complexity
hatsu38
0
350
Java 27新機能 / Java 27 new features
kishida
2
150
AWS DevOps Agentで インシデント対応をAIに任せたい
honmarkhunt
7
3k
JPUG勉強会 OSSデータベースの内部構造を理解しよう(第2回)
oga5
0
260
MVNOの申込からeSIM開通までをiOSアプリでつなぐ- 本人確認・MNP・通信事業者基盤をまたぐ実装
satotakeshi
0
440
モジュールの視点からSwiftを読み解く #iosdc
s_shimotori
0
180
JRuby: Past, Present, and Future
headius
0
130
XHTMLが残したもの
yosuke_furukawa
PRO
2
820
一人だけ、Kiroが静止する日
hideg
0
120
setup-vp GitLab対応の裏側
naokihaba
0
110
Starting & Sustaining Code-Based E2E Testing for Non-Coding QA Teams( #jasstniigata )
teyamagu
PRO
1
430
Featured
See All Featured
Art, The Web, and Tiny UX
lynnandtonic
304
22k
Cheating the UX When There Is Nothing More to Optimize - PixelPioneers
stephaniewalter
287
14k
Navigating the moral maze — ethical principles for Al-driven product design
skipperchong
2
550
ラッコキーワード サービス紹介資料
rakko
1
4.9M
Imperfection Machines: The Place of Print at Facebook
scottboms
270
14k
ピンチをチャンスに:未来をつくるプロダクトロードマップ #pmconf2020
aki_iinuma
128
56k
Kristin Tynski - Automating Marketing Tasks With AI
techseoconnect
PRO
0
520
Claude Code のすすめ
schroneko
67
230k
Exploring the Power of Turbo Streams & Action Cable | RailsConf2023
kevinliebholz
37
6.6k
Introduction to Domain-Driven Design and Collaborative software design
baasie
1
990
The Impact of AI in SEO - AI Overviews June 2024 Edition
aleyda
6
1.2k
Creating an realtime collaboration tool: Agile Flush - .NET Oxford
marcduiker
35
2.6k
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 !