Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Speaker Deck
PRO
Sign in
Sign up for free
Flutter 2021 の振り返りと今後のアプリ開発に向けて / Looking back on Flutter 2021 and for future app development.
Daichi Furiya (Wasabeef)
December 11, 2021
Programming
4
1.7k
Flutter 2021 の振り返りと今後のアプリ開発に向けて / Looking back on Flutter 2021 and for future app development.
Daichi Furiya (Wasabeef)
December 11, 2021
Tweet
Share
More Decks by Daichi Furiya (Wasabeef)
See All by Daichi Furiya (Wasabeef)
Flutter Hooks を使ったアプリ開発 / App Development with the Flutter Hooks
wasabeef
1
490
Flutter Hooks, sometimes Jetpack Compose
wasabeef
2
1.3k
Skia and Skija, Skiko [ja]
wasabeef
1
1.1k
Flutter はプロダクション開発に耐えうるのか / Flutter ready for production?
wasabeef
34
10k
モバイル開発におけるクロスプラットフォームの期待と課題 / Cross-platform expectations and challenges in mobile development
wasabeef
0
260
Repository with Store4 [ja]
wasabeef
2
980
来年に備えるために Android の知識を網羅する / Looking back on this Android year in preparation for next year.
wasabeef
17
13k
What's new Android Studio 4.0 [ja]
wasabeef
4
1.4k
What's new at Firebase Summit 2019 [ja]
wasabeef
1
450
Other Decks in Programming
See All in Programming
ふんわり理解するcontext
rukiadia
1
170
kintone × LINE Bot で餃子検定Botを作った話
naberina
0
240
実践 SpiceDB - クライドネイティブ時代をサバイブできるパーミッション管理の実装を目指して / Practical SpiceDB
lmt_swallow
0
100
Google I/O 2022 Android関連概要 / Google I/O 2022 Android summary
phicdy
0
350
Efficient UI testing in Android
alexzhukovich
1
120
Recap CDN, Edge, WebAssembly | ワインと鍋.js#1
sadnessojisan
2
1.2k
夕食断食にTRY!/for-lt-12th
pachikuriii
0
230
Haskellでオブジェクト指向プログラミング
koheisakata
0
170
kintoneでランダム取得を作ってみた(imoniCamp 2022-07-27)
shokun1108
0
130
Rに管理されてみる
kazutan
0
250
Register-based calling convention for Go functions
cjamhe01385
0
380
アジャイルで不確実性に向き合うための開発タスクの切り方
tanden
4
1.1k
Featured
See All Featured
Support Driven Design
roundedbygravity
87
8.6k
The Art of Programming - Codeland 2020
erikaheidi
32
11k
BBQ
matthewcrist
74
7.9k
Designing for Performance
lara
597
63k
The Brand Is Dead. Long Live the Brand.
mthomps
46
2.7k
Art, The Web, and Tiny UX
lynnandtonic
280
18k
Intergalactic Javascript Robots from Outer Space
tanoku
260
25k
Building Adaptive Systems
keathley
25
1.1k
Creatively Recalculating Your Daily Design Routine
revolveconf
207
10k
Navigating Team Friction
lara
175
11k
Keith and Marios Guide to Fast Websites
keithpitt
404
21k
A Philosophy of Restraint
colly
192
15k
Transcript
Flutter 2021 ͷৼΓฦΓͱ ࠓޙͷΞϓϦ։ൃʹ͚ͯ Daichi Furiya / Wasabeef CyberAgent,
Inc. Tokyo, Japan
Flutter 2021 ͷৼΓฦΓͱࠓޙͷΞϓϦ։ൃʹ͚ͯ 1. ΫϩεϓϥοτϑΥʔϜͷݱঢ়ͱ՝ 2. 2022 Flutter Λબ͢Δ͔Ͳ͏͔ 3.
Flutter ͱ Dart ͷΞοϓσʔτ 4. Flutter ΞϓϦ։ൃͷࠓޙʹ͚ͯ 4.1. ΞϓϦͷΞʔΩςΫνϟ 4.2. React ͔Βֶͼ͍ͨ͜ͱ
ΫϩεϓϥοτϑΥʔϜ ͷݱঢ়ͱ՝
ΫϩεϓϥοτϑΥʔϜͷݱঢ়ͱ՝ 1. ΫϩεϓϥοτϑΥʔϜͰ։ൃ͢Δલʹ͓͖ͬͯ͘͜ͱ 1. ϝϦοτɾσϝϦοτ 2. Kotlin Multiplatform 3. Compose
Multiplatform 2. Flutter ͷ࠾༻ࣄྫ
ΫϩεϓϥοτϑΥʔϜͰ։ൃ͢Δલʹ͓͖ͬͯ͘͜ͱ
ΫϩεϓϥοτϑΥʔϜͰ։ൃ͢Δલʹ͓͖ͬͯ͘͜ͱ • ΫϩεϓϥοτϑΥʔϜͰ։ൃ͢ΔҙຯΛߟ͑Δ → ԿΛڞ௨Խ͍͔ͨ͠ʁ • ʮͱΓ͋͑ͣ Flutter ͕ྲྀߦͬͯΔΒ͍͔͠Β
Flutter Ͱͬͱ͚ ͍͍ʯͰͳ͍ • ͜Ε·Ͱొ͖ͯͨ͠ଟͷΫϩεϓϥοτϑΥʔϜϑϨʔϜ ϫʔΫ͕ਁಁ͠ͳ͔ͬͨ͜ͱ اۀͱͯ͠औΓΉ߹
ΫϩεϓϥοτϑΥʔϜͰ։ൃ͢ΔҙຯΛߟ͑Δ QɿԿΛڞ௨Խ͍͔ͨ͠ʁ A1ɿϩδοΫ͚ͩڞ௨Խ͢Δ A2ɿUI ϩδοΫڞ௨Խ͢Δ A3ɿࠓϩδοΫ͚ͩͰকདྷతʹ ɹɹ UI ڞ௨Խ͢Δ UI
ϩδοΫ List Button Domain Label Nav Media Notification Sensors Business Logic Networking Database etc.. etc.. Log Utils
ΫϩεϓϥοτϑΥʔϜͰ։ൃ͢ΔҙຯΛߟ͑Δ QɿԿΛڞ௨Խ͍͔ͨ͠ʁ A1ɿϩδοΫ͚ͩڞ௨Խ͢Δ A2ɿUI ϩδοΫڞ௨Խ͢Δ A3ɿࠓϩδοΫ͚ͩͰকདྷతʹ ɹɹ UI ڞ௨Խ͢Δ UI
ϩδοΫ UI + ϩδοΫ
ϝϦοτɾσϝϦοτ
ϝϦοτ • ΤϯδχΞͷϦιʔεઅ • ਓɾ։ൃظؒॖ • ։ൃίϛϡχςΟͷٸతͳ ֦େʢࠃ֎ɺFlutterKaigi ͳͲʣ •
iOS/Android Ͱڞ௨ͷ UI ʢྑ͘ʣ σϝϦοτ • ΞϓϦಈ࡞ͷ҆ఆੑ ʢωΠςΟϒʹྼΔʣ • কདྷੑɺઌߦ͖ෆ҆ ʢͲͷϑϨʔϜϫʔΫΛ࠾༻͢Δ͔ʣ • iOS/Android Ͱڞ௨ͷ UI ʢѱ͘ʣ • iOS/Android ͷ৽ػೳͷ ैͷΕΔ
ΤϯδχΞͷϦιʔεઅ αʔόΤϯδχΞ iOS ΤϯδχΞ Web ΤϯδχΞ Android ΤϯδχΞ Ұൠతͳ Swift/Kotlin
ΞϓϦͷΞαΠϯελΠϧ
ΤϯδχΞͷϦιʔεઅ ΫϩεϓϥοτϑΥʔϜͰͷΞαΠϯελΠϧ ΞϓϦΤϯδχΞ ͱΓ͋͑ͣ1ਓҎ্͍Ε iOS/ Android ΞϓϦ྆ํ։ൃՄೳ αʔόΤϯδχΞ Web ΤϯδχΞ
༨
ΤϯδχΞͷϦιʔεઅ αʔόΤϯδχΞ iOS ΤϯδχΞ Web ΤϯδχΞ Android ΤϯδχΞ Ұൠతͳ Swift/Kotlin
ΞϓϦͷΞαΠϯελΠϧ ϨϏϡʔ͞Εͳ͍ෆ҆
ΤϯδχΞͷϦιʔεઅ ΫϩεϓϥοτϑΥʔϜͰͷΞαΠϯελΠϧ αʔόΤϯδχΞ ΞϓϦΤϯδχΞ Web ΤϯδχΞ ͱΓ͋͑ͣ1ਓҎ্͍Ε iOS/ Android ΞϓϦ྆ํ։ൃՄೳ
ίʔυϨϏϡʔͰ͖ͯ݁Ռͱͯ͠ ্࣭ɻ
iOS/Android Ͱڞ௨ͷ UIʢѱ͘ʣ Flutter ϚςϦΞϧσβΠϯΛ࠾༻͍ͯ͠ΔͷͰɺѱ͘ݴ͏ ͱ iOS ͬΆ͍σβΠϯ͕ଛͳΘΕ͍ͯͨΓ͢Δ͜ͱ͕͋Γ· ͢ɻͨͩɺͦΕ։ൃͷ্ͷͨΊʹσβΠϯγεςϜ
Flutterʢڞ௨ʣͱͯ͠ߟ͑ͨํ͍͍ͱͯ͠ࢥ͍ͬͯ·͢ɻ
iOS/Android Ͱڞ௨ͷ UIʢѱ͘ʣ Cupertino widgets ͋Δఔଘࡏ͢Δ͕ᘳͰͳ͍ͷͰɺiOS Β͍͠σβΠϯʹશʹ ౿ऻ͍ͨ͠߹ΫϩεϓϥοτϑΥʔϜʹ͠ͳ͍ͱ͍͏ͷબࢶࢹʹ͍Ε͍ͨ
কདྷੑɺઌߦ͖ෆ҆ ։ൃݩͷاۀ͕͍͔ʹେ اۀͩΖ͏ͱΤϯδχΞ ίϛϡχςΟʹड͚͕ྑ ͘ͳ͍ͱྲྀߦΒͳ͍
iOS/Android ͷ৽ػೳͷैͷΕʁ ྫ͑ iOS 15ɺAndroid 12 ͷରԠ͕க໋తʹΕ͍ͯͯ։ൃͰ͖ͳ͍ͱ͍͏ײ֮ͳ ͍͕ɺ֤ OS ͷ৽
API ͷΠϯλʔϑΣʔεެ։͕ޙ͍ͰདྷΔͷࣄ࣮ͱͳΓ·͢
Kotlin Multiplatform
Kotlin Multiplatform • JetBrains ʹΑͬͯ։ൃ • UI ͷڞ௨ԽͤͣɺϏδωεϩ δοΫͷڞ௨ԽʹಛԽ͍ͯ͠Δ ʢೝূɺϩάͳͲͷڞ௨Խʣ
• Kotlin Ͱ Backends for Frontends Kotlin/LLVM Kotlin/JVM Kotlin/JVM Kotlin/JS Common code
Compose Multiplatform
Compose Multiplatform • 1.0.0 (Dec 2021) • Jetpack Compose ϕʔεͰ
Jetbrains ʹΑΔ։ൃ • ݩʑ Compose for Desktop ͩͬͨͷ • ݱࡏओʹ Desktop / Web ΞϓϦ͚ʢAndroid Ͱಈ͘ʣ • ݱஈ֊Ͱ iOS ͷެࣜαϙʔτൃද͞Ε͍ͯͳ͍ • άϥϑΟοΫΤϯδϯ Skia Λར༻͍ͯ͠Δ
Skia • άϥϑΟοΫϥΠϒϥϦ • Android, Chrome, Firefox, Blink, Flutter Ͱ࠾༻͞Ε͍ͯΔ
• Skia Vulkan ΛόοΫΤϯυΤϯδϯͱͯ͠มߋՄೳ • Android 9 Ҏ߱ɺσϑΥϧτͷϨϯμϥʔ Skia ʹͳ͍ͬͯΔ ʢ8 ͱ 9 ͰUI͕มΘͬͨͷͦͷͨΊʣɻFlutter ʹ͢ΔͱϨΠ Ϡʔ͕૿͑ΔͷͷϨϯμϥʔಉ͡
Skia • ͪΖΜ iOS Ͱ Windows Ͱಈ࡞͢Δ ରԠϓϥοτϑΥʔϜ • Windows
7, 8, 8.1, 1 0 • macOS 10.10.5 or late r • iOS 8 or late r • Android 4.1 (JellyBean) or late r • Ubuntu 14.04+, Debian 8+, openSUSE 13.3+, or Fedora Linux 24+
Flutter ͷ࠾༻ࣄྫ
Flutter ͷ࠾༻ࣄྫ https://medium.com/flutter/announcing-flutter-2-8-31d2cb7e19f5 5݄ 200,000 ΞϓϦ ↓ 12݄ 375,000 ΞϓϦ
͜͜ 6 ϲ݄Ͱ 1.87 ഒ App Store
2022 Flutter Λબ ͢Δ͔Ͳ͏͔
2022 Flutter Λબ͢Δ͔Ͳ͏͔ 1. ΫϩεϓϥοτϑΥʔϜ͔ʁ֤ϓϥοτϑΥʔϜ͔ʁ 1.1. ΞϓϦͷػೳཁ݅ʁ 1.2. ΤϯδχΞͷಘҙྖҬɺͦͷਓɺظؒʁ 2.
React Native ʁ.NET MAUI ʁ 3. Compose Multiplatform ͷ಄ʁ
ΫϩεϓϥοτϑΥʔϜ͔ʁ֤ϓϥοτϑΥʔϜʢiOS / Androidʣ͔ʁ ɹΫϩεϓϥοτϑΥʔϜɹ ɹ֤ϓϥοτϑΥʔϜʢiOS / Androidʣ • UI ϏδωεϩδοΫ͕
iOS / Android Ͱҧ͏ • ҆ఆͯ͠ΫΦϦςΟ͕ߴ͍ͷ࡞ Γ͍ͨ • iOS / Android ͷܦݧऀ͕͍Δ • εέδϡʔϧʹ༨༟͕͋Δ ྫ ྫ • UI ϏδωεϩδοΫ͕ iOS / Android Ͱಉ͡ • ٕज़ࢿతͳνϟϨϯδΛ͍ͨ͠ • iOS / Android ͷܦݧऀ͕গͳ͍ ʢΤϯδχΞͷ͕গͳ͍ʣ • εέδϡʔϧʹ༨༟͕ͳ͍
ΞϓϦͷػೳཁ݅ʁ
ΞϓϦͷػೳཁ݅ʁ • iOS ͱ Android Ͱ UI ͷମݧ͕શ͘ҧ͏ʁ →
Flutter ཱͪҐஔ͕ UI ϑϨʔϜϫʔΫͳͷͰཁ͕͍݅ͦͦ͋ͬͯͳ͍͔ • ಈըͳͲͷίϯςϯπΛදࣔ͢Δͷʹ DRM ͕ඞཁʁ → Flutter ͚ͩͰ࣮͢Δͷݱஈ֊Ͱ FairPlay ରԠͨ͠ϥΠϒϥϦ͕ͳ͍ • οοΰϦοοΰϦͷΞχϝʔγϣϯ͕͋Δʁ → ύϑΥʔϚϯε͕ωΠςΟϒΑΓྼΔͷͰཁݕূ
ΤϯδχΞͷಘҙྖҬɺͦͷਓɺظؒʁ
ΤϯδχΞͷಘҙྖҬɺͦͷਓɺظؒʁ αʔόΤϯδχΞ Web ΤϯδχΞ ਓΛ૿ͤͣʹͲ͏ʹ͔͠ͳ͍ͱ͍͚ͳ͍߹
ΤϯδχΞͷಘҙྖҬɺͦͷਓɺظؒʁ αʔόΤϯδχΞ ΞϓϦΤϯδχΞ Web ΤϯδχΞ iOS / Android ͕ࣝ΄ͱΜͲͳ͍߹ʹ ผʑʹ࡞ͬͯ྆ํΛಉ࣌ʹϦϦʔε͢Δ
ͷݱ࣮తʹෆՄೳ
ΤϯδχΞͷಘҙྖҬɺͦͷਓɺظؒʁ αʔόΤϯδχΞ ΞϓϦΤϯδχΞ Web ΤϯδχΞ ͜ͷύλʔϯͰ࣮֬ʹΫϩεϓϥοτ ϑΥʔϜ͕༗ޮʹͳͬͯ͘Δ ·ͨɺFlutter ͕ෛ࠴ʹͳΔՄೳੑ͜Ε ·ͰͷΫϩεϓϥοτϑΥʔϜϑϨʔϜ
ϫʔΫʹൺΔͱ͍ʢͱࢥ͏ʣ
React Native ʁ.NET MAUI ʁ
React Native ʁ • Web ํ໘ʹڧ͍ΤϯδχΞ͕͍Δ߹ͳͲͷબࢶ → νʔϜͷಘҙྖҬٕज़ࢿ࢈ʹΑܾͬͯఆ •
ϝϧΧϦ US ͕ React Native Ͱॻ͖ͨ͠Β͍͠ → https://link.medium.com/SNFEPzc1Rlb • Facebook Coinbase Discord Tesla ͱ͍ͬͨ༗໊ͳاۀ࠾༻ → https://reactnative.dev/showcase • npm ʹ͋Δࢿ࢈Λࢧ͑ΔͷڧΈ ʢ༨ஊɿϒϩοΫνΣʔϯؔ࿈ٕज़ React Native ͚ͷ SDK ʹ͔͠ରԠ͍ͯ͠ͳ͍߹͕ଟ͍ʣ
.NET MAUI ʢچ Xamarin.Formsʣʁ • C# ํ໘ʹڧ͍ΤϯδχΞ͕͍Δ߹ͳͲͷબࢶ → νʔϜͷಘҙྖҬٕज़ࢿ࢈ʹΑܾͬͯఆ
• ৽ܕίϩφΠϧε৮֬ೝΞϓϦ Xamarin Λ࠾༻ • .NET MAUI ʹͳΔͱ XML ΛࣙΊએݴత UI Ͱॻ͚Δ • ࣄྫ͕ Flutter React Native ʹൺΔͱগͳ͍
Compose Multiplatform ͷ಄ʁ
Compose Multiplatform ͷ಄ʁ • ಄͢Δ͔͠Εͳ͍͕ɺͦΕ͕ 2022 ʹϞόΠϧ͚ ʹ Production Ready
ʹͳΔՄೳੑ͍ → ݱஈ֊Ͱ iOS ͷਖ਼ࣜαϙʔτ͕ೖ͍ͬͯͳ͍ • ͦͷஅ͕Ͱ͖Δͷ͕͏গ͠ઌʹͳΓͦ͏
• ৽نϓϩδΣΫτ • গਓʢ1ਓʙʣ • গਓͰ྆ϓϥοτϑΥʔ ϜͰϒϥϯσΟϯάͷҰ؏ੑ Λҡ͍࣋ͨ͠ • ͱʹ͔͘ૣ͘ϦϦʔε͍ͨ͠
• ΑΓνϟϨϯδ͍ͨ͠ ྫ ɹFlutterɹ Flutter ͔ʁ Kotlin MPP ͔ʁ+ Compose Multiplatform ͔ʁ ɹKotlin MPPɹ • ৽ن / طଘϓϩδΣΫτ • େਓʢ10ਓʙʣ • iOS/AndroidΞϓϦ։ൃͷਫ਼ ௨͍ͯ͠Δ • ϦεΫΛ͍֤͑ͨϓϥοτ ϑΥʔϜͰ͚ͯσβΠϯΛ ߆Γ͍ͨ ྫ ɹ+ Compose Multiplatformɹ • ݕূʢ৽نʣϓϩδΣΫτ • গਓͰ྆ϓϥοτ ϑΥʔϜͰϒϥϯσΟϯά ͷҰ؏ੑΛҡ͍࣋ͨ͠ • ͱʹ͔͘ૣ͘ϦϦʔεͨ͠ ͍ • কདྷͷٕज़ࢿΛ͍ͨ͠
• UI ϏδωεϩδοΫڞ ௨ԽͰ͖Δ • ࣄྫ͕ଟ͍ • Google Λ৴͍ͯ͡Δ ྫ
ɹFlutterɹ Kotlin MPP + Compose ɹɹɹɹɹɹ Multiplatform • Web / React ϝϯόʔ͕ଟ͍ ʢWeb ͷࢿ࢈Λ͍͍ͨʣ • UI ϏδωεϩδοΫڞ ௨ԽͰ͖Δ • ࣄྫ͕ଟ͍ʢ͕ࠃͷ͍ྼΔʣ • Facebook Λ৴͍ͯ͡Δ • Android / Kotlin ϝϯόʔ͕ ଟ͍ʢKotlin ͷࢿ࢈Λ͍͍ͨʣ • ॳظஈ֊ϏδωεϩδοΫ ͚ͩڞ௨Խ͠ Compose Multiplatform ͕҆ఆͨ͠λ ΠϛϯάͰ UI Λॻ͖͢ύ λʔϯ • Jetbrains Λ৴͍ͯ͡Δ ྫ React Native ྫ 2022 Flutter Λબ͢Δ͔Ͳ͏͔
Flutter ͱ Dart ͷ Ξοϓσʔτ
Flutter 2.8
Flutter 2.8 1. ύϑΥʔϚϯε্ ʢGoogle Pay ͰىಈςετͰ 10 ʙ 50%
ͷ্ʣ 2. Android systrace ʹ Flutter ͷύϑΥʔϚϯετϨʔεΛૹ৴͢ΔΑ͏ʹมߋ 3. Flutter DevTools ʹ Enhance Tracing ՃʢUI δϟϯΫஅͳͲʹ༗ޮʣ 4. FirebaseʢFlutterFireʣPlugin ͷ҆ఆ൛ϦϦʔε 4.1. Firebase UI ʢೝূΟδΣοτʣͷϦϦʔε 5. Desktop ൛ͷߋ৽ʢࣈ IME αϙʔτͳͲʣ 6. Dev channel ͷഇࢭʢࠓޙ master, beta, master Ͱӡ༻ʣ https://link.medium.com/a7Md15TNPlb
Firebase UI https://link.medium.com/a7Md15TNPlb • ೝূը໘ͷΟδΣοτ • Firebase Auth Λར༻ •
Email, Google, Meta, Twitter, Apple ʹରԠ
Dart 2.15
None
Dart 2.15 1. Isolate class ͷػೳ্ 2. Constructor tear-off s
3. enum ʹ API Ճ 4. ϥΠϒϥϦ։ൃ͚Ͱ pub ʹػೳՃ https://link.medium.com/kZTQCmukPlb
Isolate ͷػೳ্ લఏͱͯ͠ɿDart Ͱ 16ms Λ͑ͯϑϨʔϜϨʔτΛམͱ͢Α͏ͳॲཧΛ͢Δ ߹ʹ Isolate Λར༻ͯ͠ Worker
Isolate Ͱ࣮ߦ͢Δ͜ͱΛਪ͞Ε͍ͯΔ ʢωοτϫʔΫϨεϙϯεΛ͍ͨͩͬͯΔ͚ͩͷΑ͏ͳॲཧͷ߹ͦͷݶΓ Ͱͳ͍ʣ Dart 2.15Ͱ Worker Isolate ͔ΒϝϞϦΛίϐʔͤͣʹ Isolate.exit() Ͱ݁ՌΛ ฦ͢͜ͱ͕Ͱ͖Δɻ Flutter ͷ compute Λطʹར༻͍ͯ͠Δ߹ Flutter 2.8 ͷΞοϓάϨʔυ͢Δ͜ͱͰࣗಈతʹύϑΥʔϚϯε্͕͢Δ https://link.medium.com/kZTQCmukPlb
https://link.medium.com/kZTQCmukPlb // Isolate.spawn final p = ReceivePort(); await Isolate.spawn(_read, p.sendPort);
await p.first; // Isolate.exit Future _read(SendPort p) async { final fileData = await File(filename).readAsString(); final jsonData = jsonDecode(fileData); Isolate.exit(p, jsonData); } final fileData = File(fileName); // compute compute(_read, jsonData); List<SearchResult> _read(File filename) { final fileData = await File(filename).readAsString(); final jsonData = jsonDecode(fileData); } Isolate ͷػೳ্ Flutter ͷ computeʢத Dart ͷ Isolateʣ Dart ͷ Isolate
Isolate ͷػೳ্ https://link.medium.com/kZTQCmukPlb void main() async { final jsonData =
await _parseInBackground(); print('number of JSON keys = ${jsonData.length}'); } // Isolate.spawn Future<Map<String, dynamic>> _parseInBackground() async { final p = ReceivePort(); await Isolate.spawn(_readAndParseJson, p.sendPort); return await p.first; } // Isolate.exit Future _readAndParseJson(SendPort p) async { final fileData = await File(filename).readAsString(); final jsonData = jsonDecode(fileData); Isolate.exit(p, jsonData); }
Constructor tear-offs https://link.medium.com/kZTQCmukPlb class Hoge { Hoge() { print(‘Called Hoge()’);
} } void main() { const hoge = Hoge.new; hoge(); } // Lambda names.forEach((name) { print(name); }); // Tear-off names.forEach(print);
Constructor tear-offs https://link.medium.com/kZTQCmukPlb class FruitWidget extends StatelessWidget { @override Widget
build(BuildContext context) { return Column( children: ['Apple', 'Orange'].map((value) => Text(value)).toList()); } } class FruitWidget extends StatelessWidget { @override Widget build(BuildContext context) { return Column( children: ['Apple', 'Orange'].map(Text.new).toList()); } } Ҏલ .map ʹϥϜμΛ͍͕ͯͨ͠ ίϯετϥΫλͰ tear-off Ͱ͖ΔΑ͏ʹͳͬͨ
enum ʹ API Ճ https://link.medium.com/kZTQCmukPlb enum MyEnum { one, two,
three } void main() { // .name Ͱྻڍ໊ͷऔಘ -> "one" print(MyEnum.one.name); } / / .byName Ͱྻڍͷݕࡧ print(MyEnum.values.byName('two') == MyEnum.two); / / .asNameMap Ͱ໊ͱͷ Map Λऔಘ final map = MyEnum.values.asNameMap(); print(map['three'] == MyEnum.three);
ϥΠϒϥϦ։ൃ͚Ͱ pub ʹػೳՃ https://link.medium.com/kZTQCmukPlb 1. ϦϦʔε࣌ʹҙਤ͠ͳ͍ Secrets ؚ͕·Εͯͳ͍͔νΣοΫ 2. ޡͬͯϦϦʔεͨ͠ͷΛ
pub.dev ͔ΒఫճͰ͖ΔΑ͏ʹ
ϦϦʔε࣌ʹҙਤ͠ͳ͍ Secrets ؚ͕·Εͯͳ͍͔νΣοΫ https://link.medium.com/kZTQCmukPlb Publishing my_package 1.0.0 to https://pub.dartlang.org: Package
validation found the following errors: * line 1, column 1 of lib/key.pem: Potential leak of Private Key detected. ╷ 1 │ ┌ - - -BEGIN PRIVATE KEY - - - 2 │ │ H0M6xpM2q+53wmsN/eYLdgtjgBd3DBmHtPilCkiFICXyaA8z9LkJ 3 │ └ - - -END PRIVATE KEY - - - ╵ * line 2, column 23 of lib/my_package.dart: Potential leak of Google OAuth Refresh Token detected. ╷ 2 │ fi nal refreshToken = "1//042ys8uoFwZrkCgYIARAAGAQSNwF-L9IrXmFYE-sfKefSpoCnyqEcsHX97Y90KY- p8TPYPPnY2IPgRXdy0QeVw7URuF5u9oUeIF0"; false_secrets: - /lib/src/hardcoded_api_key.dart - /test/localhost_certi fi cates/*.pem ྫɿdart pub publish ࣌ͷνΣοΫ ςετσʔλͱͯ͠μϛʔΛஔ͍͍ͯΔ߹ͳͲ pubspec.yaml ʹҎԼΛՃ
pub.dev ͰϦϦʔεΛఫճ https://link.medium.com/kZTQCmukPlb
DartPad
DartPad • React CodeSandbox ͷΑ͏ʹ Web ্Ͱ Dart Flutter
ͷಈ࡞ڥΛ؆୯ʹ༻ҙͰ͖ΔʢCodeSandbox ΄ͲߴػೳͰͳ͍ʣ • Ұ෦ͷطʹ༻ҙ͞Ε͍ͯΔ༗໊ͳύοέʔδར༻͢Δ ͜ͱ͕Ͱ͖ΔʢFirebaseɺhttpɺriverpodɺFlutter Hooks ͳͲʣ
DartPad
Flutter ΞϓϦ։ൃͷࠓޙ ʹ͚ͯʢݸਓࢹʣ
Flutter ΞϓϦ։ൃͷࠓޙʹ͚ͯʢݸਓࢹʣ 1. ΞϓϦͷΞʔΩςΫνϟ 2. React ͔Βֶͼ͍ͨ͜ͱ 2.1. React Hooks
2.2. React ͷΞʔΩςΫνϟ
ΞϓϦͷΞʔΩςΫνϟ
ΞϓϦͷΞʔΩςΫνϟ MVVM Bloc Redux ELM/MVU
Android ΤϯδχΞʹೃ છΈͷਂ͍Ͱ͋Ζ͏ MVVM + Repository Ͱ Flutter ͰͦΕ͕࠷దղͱ ݶΒͳ͍
View Repository ViewModel Local Source Remote Data Source MVVM Repository MVVM + Repository
͜ͷϘλϯͷঢ়ଶཧͲ͏͢Δʁ ςΩετϑΟʔϧυʹԿ͔ ͕ೖྗ͞ΕΔ·ͰϘλϯ ඇ׆ੑʹ͍ͨ͠
ViewModel Λ࡞ͬͯཧ͢Δʁ ίϯϙʔωϯτͷ୯ҐΛࡉ͔͘͢Ε ͦͷ͚ͩରʹͳΔViewModel ૿͑Δʁ ͜ͷϘλϯͷঢ়ଶཧͲ͏͢Δʁ class ChatViewModel {
String text = ''; bool enabled = false; } class ChatWidget extends HookConsumerWidget { const ChatWidget({Key? key}) : super(key: key); @override Widget build(BuildContext context, WidgetRef ref) { final viewModel = ref.watch(chatViewModelProvider); return Column( children: [ TextFormField( onChanged: (value) => viewModel.enabled = value.isNotEmpty, ), ElevatedButton( onPressed: viewModel.enabled ? () {/** Submit **/} : null, child: Text('Submit'), ), ], ); } }
ίϯϙʔωϯτ ≒ ViewModelʁ • XML ࣌ͷ Android ͩͱϨΠΞτͷ୯Ґ͕େ͖͔ͬͨ • Flutter
ͰͰ͖Δ͚ͩίϯϙʔωϯτΛখ݁͘͞ʹ࡞ Γ͍ͨ • ϑΝΠϧ૿͑͗͢ΔͷͰίϯϙʔωϯτΛࡉ͔͘͢͠ ͗ͳ͍Α͏ʹ͢Δ͔ʁʢͦͷԘക͕͍͠ʣ
class DetailViewModel { DetailData data; bool isLoading; String chatText =
''; bool submitButtonEnabled = false; Future<> fetchData(){ } Future<> postData() { } } class ChatWidget extends HookConsumerWidget { const ChatWidget({Key? key}) : super(key: key); @override Widget build(BuildContext context, WidgetRef ref) { final viewModel = ref.watch(chatViewModelProvider); return ... // TextField, Button } } ChatWidget ςΩετϑΟʔϧυͱϘλϯ͔͠ͳ͍ͷʹɺ ຊདྷ͢Δඞཁͷͳ͍ͷ·Ͱ·ͰΔ͜ͱ͕Ͱ͖ͯ͠·͏ DetailViewModel ChatWidget Ͱ Θͳ͍σʔλऔಘϩʔσΟϯάঢ়ଶͳ Ͳ͍ͬͯΔ ViewModel ͷൣғΛগ͠େ͖ͯ͘͠ΈΔʁ
؆୯ͳঢ়ଶίϯϙʔωϯτଆͰ͍࣋ͪͨ ʴ ؆୯ʹॻ͖͍ͨ class CountPage extends StatefulWidget { @override State
createState() => _CountState(); } class _CountState extends State<CountPage> { int count = 0; @override void initState() { /** ॳظԽ **/ } @override void dispose() { /** ഁغ **/ } void setCount(int value) => setState(() => count = value); @override Widget build(BuildContext context) { return TextButton( child: Text(“Count: $count"), onPressed: () => setCount(count + 1), ); } } Flutter Hooks Ͱॻ͘ class CountPage extends HookWidget { @override Widget build(BuildContext context) { final count = useState(0); return TextButton( child: Text("Count: ${count.value}"), onPressed: () => count.value++, ); } }
Flutter Hooks
LaunchedEffect(id) { // ID ͕มߋ͞ΕΔͨͼ } SideEffect { // ຖճ
} LaunchedEffect(Unit) { // ࠷ॳͷҰճ } 73 useEffect useEffect(() => { // ID ͕มߋ͞ΕΔͨͼ }, [id]); useEffect(() => { // ຖճ }); useEffect(() => { // ࠷ॳͷҰճ }, const []); Flutter Hooks Jetpack Compose
ViewModel ͔ΒϘλϯͳͲͷঢ়ଶཧΛࠩ͠Ҿ͍͍ͯ͘ͱ ViewModel ͡Όͳ͍͍͔ͯ͘͠Εͳ͍ ↓ MVVM ͡Όͳ͍͔… ʢ࣮ࡍʹଞʹ৭ʑΉͣᙱ͍ͱ͜Ζ͕͋Δʣ ΞʔΩςΫνϟΛߟ͑͢
࠷ۙϨΠϠʔଟ͗͢ΔͬͱݮΒ͍͖͍ͯͨ͠ ↓ Flutter ΞϓϦք۾ͷઃܭ͕ఆ·ͬͯͳ͍͔ΒReact ͔ΒֶͿ͔ ΞʔΩςΫνϟΛߟ͑͢
React ͔Βֶͼ͍ͨ͜ͱ
React ͔Βֶͼ͍ͨ͜ͱʢݸਓࢹʣ 1. React App ͷΞʔΩςΫνϟ 2. React Hooks ͷ͍Ͳ͜Ζ
3. ίϯϙʔωϯτ୯ҐͰͷςετ
• Redux • Recoil • + React Query / SWR
React App ͷΞʔΩςΫνϟ
• React Hook ͬͯσʔλऔಘ͢Δ ͨΊͷϥΠϒϥϦ • ίϯϙʔωϯτଆͰ API ͷωοτ ϫʔΫϦΫΤετΛ͢Δ
• ΩϟογϡϦΫΤετͷॏෳഉ আͳͲϥΠϒϥϦଆ͕ߦ͏ React Query / SWR import useSWR from 'swr' function Profile() { const { data, error } = useSWR('/api/user', fetcher) if (error) return <div>failed to load</div> if (!data) return <div>loading...</div> return <div>hello {data.name}!</div> }
• react-use react-hooks-testing-library ͔Β Ϣʔεέʔεͦͷςετํ๏ͳͲΛֶΜͰ Flutter ք۾ʹө͢Δ React Hooks
ͷ͍Ͳ͜Ζ
react-use • ศརͳ Custom Hooks ͕ͨ͘͞Μؚ·Ε͍ͯΔ ϥΠϒϥϦ • npm i
react-use ͍͍ͯͬͯ͠͠ɺ Unlicense ͳͷͰҰ෦Λίϐϖ͍͍ͯͬͯ͠
react-use
import { useNetworkState } from 'react-use'; const Demo = ()
=> { const state = useNetworkState(); return ( <pre> {JSON.stringify(state, null, 2)} </pre> ); }; ྫ͑ useNetworkState Λ͏ͱ ͷωοτϫʔΫঢ়ଶΛࢹͯ͠ঢ় ଶ͕มΘͬͨΒϦϏϧυͯ͠Λऔ ಘͰ͖ΔΑ͏ʹ͢Δ react-use
react-hooks-testing-library test('should increment counter', () => { const { result
} = renderHook(() => useCounter()) act(() => { result.current.increment() }) expect(result.current.count).toBe(1) }) ࣗ࡞ Hooks ͷςετΛॻ͘ʹίϯ ϙʔωϯτΛߋ৽͢ΔͨΊͷτϦ ΨʔΛॻ͍ͯ࠶ϨϯμϦϯάͤͨ͞ ΓɺΛߋ৽͢ΔͨΊͷίʔυΛॻ ͍ͨΓ͠ͳ͚Ε͍͚ͳ͔ͬͨͷ Λ؆୯ʹ͔͚ΔΑ͏ʹ͢Δ
react-hooks-testing-library testWidgets('debugFillProperties', (tester) async { await tester.pumpWidget( HookBuilder(builder: (context) {
usePrevious(42); return const SizedBox(); }), ); await tester.pumpWidget( HookBuilder(builder: (context) { usePrevious(21); return const SizedBox(); }), ); final element = tester.element(find.byType(HookBuilder)); expect( element .toDiagnosticsNode(style: DiagnosticsTreeStyle.offstage) .toStringDeep(), equalsIgnoringHashCodes( 'HookBuilder\n' ' │ usePrevious: 42\n' ' └SizedBox(renderObject: RenderConstrainedBox#00000)\n', ), ); }); ࢀߟίʔυͱͯ͠ Flutter Hooks ͔Β ͖࣋ͬͯͨ usePrevious ͷςετίʔ υ͕ͪ͜ΒʹͳΓ·͢ ᶃ Ͱ 42 Λ usePrevious ʹ͢ ᶄ Ͱ 21 Λ usePrevious ʹ͢ ᶅ Ͱ usePrevious ͷঢ়ଶΛ֬ೝ͢Δ ᶃ ᶄ ᶅ
react-hooks-testing-library testWidgets('debugFillProperties', (tester) async { final result = await buildHook(
(value) => usePrevious(value), initialProps: 42, ); await result.rebuild(21); expect(result.current, 42); }); ͠Ծʹ Flutter Ͱಉ͡Α͏ͳ͜ͱ͕Ͱ͖ ͨͱͨ͠Βɺ͜Ε͘Β͍ͷίʔυྔͰ͢ react-hooks-testing-library ͦΕ͘Β͍ ϘΠϥʔίʔυΛݮͰ͖ΔϥΠϒϥϦ ᶃ ᶄ ᶅ
flutter_use ͱ flutter_hooks_testing
·ͱΊ
·ͱΊ • ΫϥΠΞϯταΠυ͕શͯએݴత UI ͷํʹͳͬͯ͘Ε͓ͨ ͔͛Ͱ Flutter Ͱ࡞Δʹͯ͠ React ͔Βֶͯ
Jetpack Compose Ͱ࡞Δʹͯ͠ࢀߟʹͳΔͷ͕ΰϩΰϩͱస ͕͍ͬͯΔ • ֤ݴޠͷҧ͍ͳΜͯࠣࡉͳͷͰ UI ϑϨʔϜϫʔΫΛͦΕͧ ΕֶͿͷ͕େม͚ͩͬͨͲɺ༏͍͠ੈքʹͳ͖ͬͯͨ
Google Developers Expert @wasabeef_jp wasabeef CyberAgent, Inc.