Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Flutter 2021 の振り返りと今後のアプリ開発に向けて / Looking back on Flutter 2021 and for future app development.

Flutter 2021 の振り返りと今後のアプリ開発に向けて / Looking back on Flutter 2021 and for future app development.

Daichi Furiya (Wasabeef)

December 11, 2021
Tweet

More Decks by Daichi Furiya (Wasabeef)

Other Decks in Programming

Transcript

  1. Flutter 2021 ͷৼΓฦΓͱ 
 ࠓޙͷΞϓϦ։ൃʹ޲͚ͯ Daichi Furiya / Wasabeef CyberAgent,

    Inc. Tokyo, Japan
  2. Flutter 2021 ͷৼΓฦΓͱࠓޙͷΞϓϦ։ൃʹ޲͚ͯ 1. ΫϩεϓϥοτϑΥʔϜͷݱঢ়ͱ՝୊ 2. 2022೥΋ Flutter Λબ୒͢Δ͔Ͳ͏͔ 3.

    Flutter ͱ Dart ͷΞοϓσʔτ 4. Flutter ΞϓϦ։ൃͷࠓޙʹ޲͚ͯ 4.1. ΞϓϦͷΞʔΩςΫνϟ 4.2. React ͔Βֶͼ͍ͨ͜ͱ
  3. ΫϩεϓϥοτϑΥʔϜ ͷݱঢ়ͱ՝୊

  4. ΫϩεϓϥοτϑΥʔϜͷݱঢ়ͱ՝୊ 1. ΫϩεϓϥοτϑΥʔϜͰ։ൃ͢Δલʹ஌͓ͬͯ͘΂͖͜ͱ 1. ϝϦοτɾσϝϦοτ 2. Kotlin Multiplatform 3. Compose

    Multiplatform 2. Flutter ͷ࠾༻ࣄྫ
  5. ΫϩεϓϥοτϑΥʔϜͰ։ൃ͢Δલʹ஌͓ͬͯ͘΂͖͜ͱ

  6. ΫϩεϓϥοτϑΥʔϜͰ։ൃ͢Δલʹ஌͓ͬͯ͘΂͖͜ͱ • ΫϩεϓϥοτϑΥʔϜͰ։ൃ͢ΔҙຯΛߟ͑Δ 
 → ԿΛڞ௨Խ͍͔ͨ͠ʁ • ʮͱΓ͋͑ͣ Flutter ͕ྲྀߦͬͯΔΒ͍͔͠Β

    Flutter Ͱ΍ͬͱ͚ ͹͍͍ʯͰ͸ͳ͍ • ͜Ε·Ͱొ৔͖ͯͨ͠਺ଟͷΫϩεϓϥοτϑΥʔϜϑϨʔϜ ϫʔΫ͕ਁಁ͠ͳ͔ͬͨ͜ͱ اۀͱͯ͠औΓ૊Ή৔߹
  7. ΫϩεϓϥοτϑΥʔϜͰ։ൃ͢ΔҙຯΛߟ͑Δ QɿԿΛڞ௨Խ͍͔ͨ͠ʁ A1ɿϩδοΫ͚ͩڞ௨Խ͢Δ A2ɿUI ΋ϩδοΫ΋ڞ௨Խ͢Δ A3ɿࠓ͸ϩδοΫ͚ͩͰকདྷతʹ͸ ɹɹ UI ΋ڞ௨Խ͢Δ UI

    ϩδοΫ List Button Domain Label Nav Media Notification Sensors Business Logic Networking Database etc.. etc.. Log Utils
  8. ΫϩεϓϥοτϑΥʔϜͰ։ൃ͢ΔҙຯΛߟ͑Δ QɿԿΛڞ௨Խ͍͔ͨ͠ʁ A1ɿϩδοΫ͚ͩڞ௨Խ͢Δ A2ɿUI ΋ϩδοΫ΋ڞ௨Խ͢Δ A3ɿࠓ͸ϩδοΫ͚ͩͰকདྷతʹ͸ ɹɹ UI ΋ڞ௨Խ͢Δ UI

    ϩδοΫ UI + ϩδοΫ
  9. ϝϦοτɾσϝϦοτ

  10. ϝϦοτ • ΤϯδχΞͷϦιʔεઅ໿ • ਓ਺ɾ։ൃظؒ୹ॖ • ։ൃίϛϡχςΟͷٸ଎తͳ ֦େʢࠃ಺֎ɺFlutterKaigi ͳͲʣ •

    iOS/Android Ͱڞ௨ͷ UI 
 ʢྑ͘΋ʣ σϝϦοτ • ΞϓϦಈ࡞ͷ҆ఆੑ 
 ʢωΠςΟϒʹ͸ྼΔʣ • কདྷੑɺઌߦ͖ෆ҆ 
 ʢͲͷϑϨʔϜϫʔΫΛ࠾༻͢Δ͔ʣ • iOS/Android Ͱڞ௨ͷ UI 
 ʢѱ͘΋ʣ • iOS/Android ͷ৽ػೳ΁ͷ௥ ैͷ஗ΕΔ
  11. ΤϯδχΞͷϦιʔεઅ໿ αʔόΤϯδχΞ iOS ΤϯδχΞ Web ΤϯδχΞ Android ΤϯδχΞ Ұൠతͳ Swift/Kotlin

    ΞϓϦͷΞαΠϯελΠϧ
  12. ΤϯδχΞͷϦιʔεઅ໿ ΫϩεϓϥοτϑΥʔϜͰͷΞαΠϯελΠϧ ΞϓϦΤϯδχΞ ͱΓ͋͑ͣ1ਓҎ্͍Ε͹ iOS/ Android ΞϓϦ྆ํ։ൃՄೳ αʔόΤϯδχΞ Web ΤϯδχΞ

    ༨৒
  13. ΤϯδχΞͷϦιʔεઅ໿ αʔόΤϯδχΞ iOS ΤϯδχΞ Web ΤϯδχΞ Android ΤϯδχΞ Ұൠతͳ Swift/Kotlin

    ΞϓϦͷΞαΠϯελΠϧ ϨϏϡʔ͞Εͳ͍ෆ҆
  14. ΤϯδχΞͷϦιʔεઅ໿ ΫϩεϓϥοτϑΥʔϜͰͷΞαΠϯελΠϧ αʔόΤϯδχΞ ΞϓϦΤϯδχΞ Web ΤϯδχΞ ͱΓ͋͑ͣ1ਓҎ্͍Ε͹ iOS/ Android ΞϓϦ྆ํ։ൃՄೳ

    ίʔυϨϏϡʔͰ͖ͯ݁Ռͱͯ͠ ඼࣭޲্΋ɻ
  15. iOS/Android Ͱڞ௨ͷ UIʢѱ͘΋ʣ Flutter ͸ϚςϦΞϧσβΠϯΛ࠾༻͍ͯ͠ΔͷͰɺѱ͘ݴ͏ ͱ iOS ͬΆ͍σβΠϯ͕ଛͳΘΕ͍ͯͨΓ͢Δ͜ͱ͕͋Γ· ͢ɻͨͩɺͦΕ͸։ൃ଎౓ͷ޲্ͷͨΊʹσβΠϯγεςϜ ͸

    Flutterʢڞ௨ʣͱͯ͠ߟ͑ͨํ͍͍ͱͯ͠ࢥ͍ͬͯ·͢ɻ
  16. iOS/Android Ͱڞ௨ͷ UIʢѱ͘΋ʣ Cupertino widgets ΋͋Δఔ౓ଘࡏ͢Δ͕׬ᘳͰ͸ͳ͍ͷͰɺiOS Β͍͠σβΠϯʹ׬શʹ ౿ऻ͍ͨ͠৔߹͸ΫϩεϓϥοτϑΥʔϜʹ͸͠ͳ͍ͱ͍͏ͷબ୒ࢶ΋ࢹ໺ʹ͍Ε͍ͨ

  17. কདྷੑɺઌߦ͖ෆ҆ ։ൃݩͷاۀ͕͍͔ʹେ اۀͩΖ͏ͱΤϯδχΞ ίϛϡχςΟʹड͚͕ྑ ͘ͳ͍ͱྲྀߦΒͳ͍

  18. iOS/Android ͷ৽ػೳ΁ͷ௥ैͷ஗Εʁ ྫ͑͹ iOS 15ɺAndroid 12 ͷରԠ͕க໋తʹ஗Ε͍ͯͯ։ൃͰ͖ͳ͍ͱ͍͏ײ֮͸ͳ ͍͕ɺ֤ OS ͷ৽

    API ͷΠϯλʔϑΣʔεެ։͕ޙ௥͍ͰདྷΔͷ͸ࣄ࣮ͱͳΓ·͢
  19. Kotlin Multiplatform

  20. Kotlin Multiplatform • JetBrains ʹΑͬͯ։ൃ • UI ͷڞ௨Խ͸ͤͣɺϏδωεϩ δοΫͷڞ௨ԽʹಛԽ͍ͯ͠Δ ʢೝূɺϩάͳͲͷڞ௨Խʣ

    • Kotlin Ͱ Backends for Frontends Kotlin/LLVM Kotlin/JVM Kotlin/JVM Kotlin/JS Common code
  21. Compose Multiplatform

  22. Compose Multiplatform • 1.0.0 (Dec 2021) • Jetpack Compose ϕʔεͰ

    Jetbrains ʹΑΔ։ൃ • ݩʑ͸ Compose for Desktop ͩͬͨ΋ͷ • ݱࡏ͸ओʹ Desktop / Web ΞϓϦ޲͚ʢAndroid Ͱ΋ಈ͘ʣ • ݱஈ֊Ͱ͸ iOS ΁ͷެࣜαϙʔτ͸ൃද͞Ε͍ͯͳ͍ • άϥϑΟοΫΤϯδϯ͸ Skia Λར༻͍ͯ͠Δ
  23. Skia • άϥϑΟοΫϥΠϒϥϦ • Android, Chrome, Firefox, Blink, Flutter Ͱ࠾༻͞Ε͍ͯΔ

    • Skia ͸ Vulkan ΛόοΫΤϯυΤϯδϯͱͯ͠มߋՄೳ • Android 9 Ҏ߱ɺσϑΥϧτͷϨϯμϥʔ͸ Skia ʹͳ͍ͬͯΔ ʢ8 ͱ 9 ͰUI͕มΘͬͨͷ͸ͦͷͨΊʣɻFlutter ʹ͢ΔͱϨΠ Ϡʔ͕૿͑Δ΋ͷͷϨϯμϥʔ͸ಉ͡
  24. 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+
  25. Flutter ͷ࠾༻ࣄྫ

  26. Flutter ͷ࠾༻ࣄྫ https://medium.com/flutter/announcing-flutter-2-8-31d2cb7e19f5 5݄ 200,000 ΞϓϦ ↓ 12݄ 375,000 ΞϓϦ

    ͜͜ 6 ϲ݄Ͱ 1.87 ഒ App Store
  27. 2022೥΋ Flutter Λબ୒ ͢Δ͔Ͳ͏͔

  28. 2022೥΋ Flutter Λબ୒͢Δ͔Ͳ͏͔ 1. ΫϩεϓϥοτϑΥʔϜ͔ʁ֤ϓϥοτϑΥʔϜ͔ʁ 1.1. ΞϓϦͷػೳཁ݅͸ʁ 1.2. ΤϯδχΞͷಘҙྖҬɺͦͷਓ਺ɺظؒ͸ʁ 2.

    React Native ͸ʁ.NET MAUI ͸ʁ 3. Compose Multiplatform ͷ୆಄͸ʁ
  29. ΫϩεϓϥοτϑΥʔϜ͔ʁ֤ϓϥοτϑΥʔϜʢiOS / Androidʣ͔ʁ ɹΫϩεϓϥοτϑΥʔϜɹ ɹ֤ϓϥοτϑΥʔϜʢiOS / Androidʣ • UI ΍ϏδωεϩδοΫ͕

    iOS / Android Ͱҧ͏ • ҆ఆͯ͠ΫΦϦςΟ͕ߴ͍΋ͷ࡞ Γ͍ͨ • iOS / Android ͷܦݧऀ͕͍Δ • εέδϡʔϧʹ༨༟͕͋Δ ྫ ྫ • UI ΍ϏδωεϩδοΫ͕ iOS / Android Ͱಉ͡ • ٕज़౤ࢿతͳνϟϨϯδΛ͍ͨ͠ • iOS / Android ͷܦݧऀ͕গͳ͍ 
 ʢΤϯδχΞͷ਺͕গͳ͍ʣ • εέδϡʔϧʹ༨༟͕ͳ͍
  30. ΞϓϦͷػೳཁ݅͸ʁ

  31. ΞϓϦͷػೳཁ݅͸ʁ • iOS ͱ Android Ͱ UI ͷମݧ͕શ͘ҧ͏ʁ 
 →

    Flutter ͸ཱͪҐஔ͕ UI ϑϨʔϜϫʔΫͳͷͰཁ͕݅ͦ΋ͦ΋͍͋ͬͯͳ͍͔΋ • ಈըͳͲͷίϯςϯπΛදࣔ͢Δͷʹ DRM ͕ඞཁʁ 
 → Flutter ͚ͩͰ࣮૷͢Δͷ͸ݱஈ֊Ͱ͸ FairPlay ରԠͨ͠ϥΠϒϥϦ͕ͳ͍ • οοΰϦοοΰϦͷΞχϝʔγϣϯ͕͋Δʁ 
 → ύϑΥʔϚϯε͕ωΠςΟϒΑΓྼΔͷͰཁݕূ
  32. ΤϯδχΞͷಘҙྖҬɺͦͷਓ਺ɺظؒ͸ʁ

  33. ΤϯδχΞͷಘҙྖҬɺͦͷਓ਺ɺظؒ͸ʁ αʔόΤϯδχΞ Web ΤϯδχΞ ਓΛ૿΍ͤͣʹͲ͏ʹ͔͠ͳ͍ͱ͍͚ͳ͍৔߹

  34. ΤϯδχΞͷಘҙྖҬɺͦͷਓ਺ɺظؒ͸ʁ αʔόΤϯδχΞ ΞϓϦΤϯδχΞ Web ΤϯδχΞ iOS / Android ஌͕ࣝ΄ͱΜͲͳ͍৔߹ʹ ผʑʹ࡞ͬͯ྆ํΛಉ࣌ʹϦϦʔε͢Δ

    ͷ͸ݱ࣮తʹ͸ෆՄೳ
  35. ΤϯδχΞͷಘҙྖҬɺͦͷਓ਺ɺظؒ͸ʁ αʔόΤϯδχΞ ΞϓϦΤϯδχΞ Web ΤϯδχΞ ͜ͷύλʔϯͰ͸࣮֬ʹΫϩεϓϥοτ ϑΥʔϜ͕༗ޮʹͳͬͯ͘Δ ·ͨɺFlutter ͕ෛ࠴ʹͳΔՄೳੑ΋͜Ε ·ͰͷΫϩεϓϥοτϑΥʔϜϑϨʔϜ

    ϫʔΫʹൺ΂Δͱ௿͍ʢͱࢥ͏ʣ
  36. React Native ͸ʁ.NET MAUI ͸ʁ

  37. React Native ͸ʁ • Web ํ໘ʹڧ͍ΤϯδχΞ͕͍Δ৔߹ͳͲͷબ୒ࢶ 
 → νʔϜͷಘҙྖҬ΍ٕज़ࢿ࢈ʹΑܾͬͯఆ •

    ϝϧΧϦ US ͕ React Native Ͱॻ͖௚ͨ͠Β͍͠ 
 → https://link.medium.com/SNFEPzc1Rlb • Facebook ΍ Coinbase ΍ Discord ΍ Tesla ͱ͍ͬͨ༗໊ͳاۀ΋࠾༻ 
 → https://reactnative.dev/showcase • npm ʹ͋Δࢿ࢈Λࢧ͑Δͷ͸ڧΈ 
 ʢ༨ஊɿϒϩοΫνΣʔϯؔ࿈ٕज़͸ React Native ޲͚ͷ SDK ʹ͔͠ରԠ͍ͯ͠ͳ͍৔߹͕ଟ͍ʣ
  38. .NET MAUI ʢچ Xamarin.Formsʣ͸ʁ • C# ํ໘ʹڧ͍ΤϯδχΞ͕͍Δ৔߹ͳͲͷબ୒ࢶ 
 → νʔϜͷಘҙྖҬ΍ٕज़ࢿ࢈ʹΑܾͬͯఆ

    • ৽ܕίϩφ΢Πϧε઀৮֬ೝΞϓϦ͸ Xamarin Λ࠾༻ • .NET MAUI ʹͳΔͱ XML ΛࣙΊએݴత UI Ͱॻ͚Δ • ࣄྫ͕ Flutter ΍ React Native ʹൺ΂Δͱগͳ͍
  39. Compose Multiplatform ͷ୆಄͸ʁ

  40. Compose Multiplatform ͷ୆಄͸ʁ • ୆಄͢Δ͔΋͠Εͳ͍͕ɺͦΕ͕ 2022 ೥ʹϞόΠϧ޲͚ ʹ Production Ready

    ʹͳΔՄೳੑ͸௿͍ 
 → ݱஈ֊Ͱ iOS ͷਖ਼ࣜαϙʔτ͕ೖ͍ͬͯͳ͍ • ͦͷ൑அ͕Ͱ͖Δͷ͕΋͏গ͠ઌʹͳΓͦ͏
  41. • ৽نϓϩδΣΫτ • গਓ਺ʢ1ਓʙʣ • গਓ਺Ͱ΋྆ϓϥοτϑΥʔ ϜͰϒϥϯσΟϯάͷҰ؏ੑ Λҡ͍࣋ͨ͠ • ͱʹ͔͘ૣ͘ϦϦʔε͍ͨ͠

    • ΑΓνϟϨϯδ͍ͨ͠ ྫ ɹFlutterɹ Flutter ͔ʁ Kotlin MPP ͔ʁ+ Compose Multiplatform ͔ʁ ɹKotlin MPPɹ • ৽ن / طଘϓϩδΣΫτ • େਓ਺ʢ10ਓʙʣ • iOS/AndroidΞϓϦ։ൃͷਫ਼ ௨͍ͯ͠Δ • ϦεΫΛ཈͍֤͑ͨϓϥοτ ϑΥʔϜͰ෼͚ͯσβΠϯΛ ߆Γ͍ͨ ྫ ɹ+ Compose Multiplatformɹ • ݕূʢ৽نʣϓϩδΣΫτ • গਓ਺Ͱ΋྆ϓϥοτ ϑΥʔϜͰϒϥϯσΟϯά ͷҰ؏ੑΛҡ͍࣋ͨ͠ • ͱʹ͔͘ૣ͘ϦϦʔεͨ͠ ͍ • কདྷ΁ͷٕज़౤ࢿΛ͍ͨ͠
  42. • UI ΋ϏδωεϩδοΫ΋ڞ ௨ԽͰ͖Δ • ࣄྫ͕ଟ͍ • Google Λ৴͍ͯ͡Δ ྫ

    ɹFlutterɹ Kotlin MPP + Compose ɹɹɹɹɹɹ Multiplatform • Web / React ϝϯόʔ͕ଟ͍ 
 ʢWeb ͷࢿ࢈Λ࢖͍͍ͨʣ • UI ΋ϏδωεϩδοΫ΋ڞ ௨ԽͰ͖Δ • ࣄྫ͕ଟ͍ʢ͕ࠃ಺ͷ੎͍͸ྼΔʣ • Facebook Λ৴͍ͯ͡Δ • Android / Kotlin ϝϯόʔ͕ ଟ͍ʢKotlin ͷࢿ࢈Λ࢖͍͍ͨʣ • ॳظஈ֊͸ϏδωεϩδοΫ ͚ͩڞ௨Խ͠ Compose Multiplatform ͕҆ఆͨ͠λ ΠϛϯάͰ UI Λॻ͖௚͢ύ λʔϯ • Jetbrains Λ৴͍ͯ͡Δ ྫ React Native ྫ 2022೥΋ Flutter Λબ୒͢Δ͔Ͳ͏͔
  43. Flutter ͱ Dart ͷ Ξοϓσʔτ

  44. Flutter 2.8

  45. 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
  46. Firebase UI https://link.medium.com/a7Md15TNPlb • ೝূը໘ͷ΢ΟδΣοτ • Firebase Auth Λར༻ •

    Email, Google, Meta, Twitter, Apple ʹରԠ
  47. Dart 2.15

  48. None
  49. Dart 2.15 1. Isolate class ͷػೳ޲্ 2. Constructor tear-off s

    3. enum ʹ API ௥Ճ 4. ϥΠϒϥϦ։ൃ޲͚Ͱ pub ʹػೳ௥Ճ https://link.medium.com/kZTQCmukPlb
  50. Isolate ͷػೳ޲্ લఏͱͯ͠ɿDart Ͱ 16ms Λ௒͑ͯϑϨʔϜϨʔτΛམͱ͢Α͏ͳॲཧΛ͢Δ ৔߹ʹ͸ Isolate Λར༻ͯ͠ Worker

    Isolate Ͱ࣮ߦ͢Δ͜ͱΛਪ঑͞Ε͍ͯΔ ʢωοτϫʔΫϨεϙϯεΛͨͩ଴͍ͬͯΔ͚ͩͷΑ͏ͳॲཧͷ৔߹ͦͷݶΓ Ͱ͸ͳ͍ʣ Dart 2.15Ͱ͸ Worker Isolate ͔ΒϝϞϦΛίϐʔͤͣʹ Isolate.exit() Ͱ݁ՌΛ ฦ͢͜ͱ͕Ͱ͖Δɻ Flutter ͷ compute Λطʹར༻͍ͯ͠Δ৔߹͸ Flutter 2.8 ͷΞοϓάϨʔυ͢Δ͜ͱͰࣗಈతʹύϑΥʔϚϯε͕޲্͢Δ https://link.medium.com/kZTQCmukPlb
  51. 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
  52. 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); }
  53. 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);
  54. 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 Ͱ͖ΔΑ͏ʹͳͬͨ
  55. 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);
  56. ϥΠϒϥϦ։ൃ޲͚Ͱ pub ʹػೳ௥Ճ https://link.medium.com/kZTQCmukPlb 1. ϦϦʔε࣌ʹҙਤ͠ͳ͍ Secrets ؚ͕·Εͯͳ͍͔νΣοΫ 2. ޡͬͯϦϦʔεͨ͠΋ͷΛ

    pub.dev ͔ΒఫճͰ͖ΔΑ͏ʹ
  57. ϦϦʔε࣌ʹҙਤ͠ͳ͍ 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 ʹҎԼΛ௥Ճ
  58. pub.dev ͰϦϦʔεΛఫճ https://link.medium.com/kZTQCmukPlb

  59. DartPad

  60. DartPad • React CodeSandbox ͷΑ͏ʹ Web ্Ͱ Dart ΍ Flutter

    ͷಈ࡞؀ڥΛ؆୯ʹ༻ҙͰ͖ΔʢCodeSandbox ΄ͲߴػೳͰ͸ͳ͍ʣ • Ұ෦ͷطʹ༻ҙ͞Ε͍ͯΔ༗໊ͳύοέʔδ΋ར༻͢Δ ͜ͱ͕Ͱ͖ΔʢFirebaseɺhttpɺriverpodɺFlutter Hooks ͳͲʣ
  61. DartPad

  62. Flutter ΞϓϦ։ൃͷࠓޙ ʹ޲͚ͯʢݸਓࢹ఺ʣ

  63. Flutter ΞϓϦ։ൃͷࠓޙʹ޲͚ͯʢݸਓࢹ఺ʣ 1. ΞϓϦͷΞʔΩςΫνϟ 2. React ͔Βֶͼ͍ͨ͜ͱ 2.1. React Hooks

    2.2. React ͷΞʔΩςΫνϟ
  64. ΞϓϦͷΞʔΩςΫνϟ

  65. ΞϓϦͷΞʔΩςΫνϟ MVVM Bloc Redux ELM/MVU

  66. Android ΤϯδχΞʹ͸ೃ છΈͷਂ͍Ͱ͋Ζ͏ MVVM + Repository Ͱ΋ Flutter ͰͦΕ͕࠷దղͱ ͸ݶΒͳ͍

    View Repository ViewModel Local Source Remote Data Source MVVM Repository MVVM + Repository
  67. ͜ͷϘλϯͷঢ়ଶ؅ཧ͸Ͳ͏͢Δʁ ςΩετϑΟʔϧυʹԿ͔ ͕ೖྗ͞ΕΔ·ͰϘλϯ͸ ඇ׆ੑʹ͍ͨ͠

  68. 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'), ), ], ); } }
  69. ίϯϙʔωϯτ਺ ≒ ViewModel਺ʁ • XML ࣌୅ͷ Android ͩͱϨΠΞ΢τͷ୯Ґ͕େ͖͔ͬͨ • Flutter

    Ͱ͸Ͱ͖Δ͚ͩίϯϙʔωϯτΛখ͘͞׬݁ʹ࡞ Γ͍ͨ • ϑΝΠϧ਺૿͑͗͢ΔͷͰίϯϙʔωϯτΛࡉ͔͘͢͠ ͗ͳ͍Α͏ʹ͢Δ͔ʁʢͦͷԘക͕೉͍͠ʣ
  70. 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 ͷൣғΛগ͠େ͖ͯ͘͠ΈΔʁ
  71. ؆୯ͳঢ়ଶ͸ίϯϙʔωϯτଆͰ͍࣋ͪͨ ʴ ؆୯ʹॻ͖͍ͨ 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++, ); } }
  72. Flutter Hooks

  73. LaunchedEffect(id) { // ID ͕มߋ͞ΕΔͨͼ } SideEffect { // ຖճ

    } LaunchedEffect(Unit) { // ࠷ॳͷҰճ } 73 useEffect useEffect(() => { // ID ͕มߋ͞ΕΔͨͼ }, [id]); useEffect(() => { // ຖճ }); useEffect(() => { // ࠷ॳͷҰճ }, const []); Flutter Hooks Jetpack Compose
  74. ViewModel ͔ΒϘλϯͳͲͷঢ়ଶ؅ཧΛࠩ͠Ҿ͍͍ͯ͘ͱ ViewModel ͡Όͳ͍͍͔ͯ͘΋͠Εͳ͍ ↓ MVVM ͡Όͳ͍͔΋… 
 ʢ࣮ࡍʹ͸ଞʹ΋৭ʑΉͣᙱ͍ͱ͜Ζ͕͋Δʣ ΞʔΩςΫνϟΛߟ͑௚͢

  75. ࠷ۙ͸ϨΠϠʔଟ͗͢Δ΋ͬͱݮΒ͍͖͍ͯͨ͠ ↓ Flutter ΞϓϦք۾ͷઃܭ͕ఆ·ͬͯͳ͍͔ΒReact ͔ΒֶͿ͔ ΞʔΩςΫνϟΛߟ͑௚͢

  76. React ͔Βֶͼ͍ͨ͜ͱ

  77. React ͔Βֶͼ͍ͨ͜ͱʢݸਓࢹ఺ʣ 1. React App ͷΞʔΩςΫνϟ 2. React Hooks ͷ࢖͍Ͳ͜Ζ

    3. ίϯϙʔωϯτ୯ҐͰͷςετ
  78. • Redux • Recoil • + React Query / SWR

    React App ͷΞʔΩςΫνϟ
  79. • 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> }
  80. • react-use ΍ react-hooks-testing-library ͔Β Ϣʔεέʔε΍ͦͷςετํ๏ͳͲΛֶΜͰ Flutter ք۾ʹ൓ө͢Δ React Hooks

    ͷ࢖͍Ͳ͜Ζ
  81. react-use • ศརͳ Custom Hooks ͕ͨ͘͞Μؚ·Ε͍ͯΔ ϥΠϒϥϦ • npm i

    react-use ͯ͠࢖ͬͯ΋͍͍͠ɺ Unlicense ͳͷͰҰ෦Λίϐϖͯ͠࢖ͬͯ΋͍͍
  82. react-use

  83. import { useNetworkState } from 'react-use'; const Demo = ()

    => { const state = useNetworkState(); return ( <pre> {JSON.stringify(state, null, 2)} </pre> ); }; ྫ͑͹ useNetworkState Λ࢖͏ͱ୺ ຤ͷωοτϫʔΫঢ়ଶΛ؂ࢹͯ͠ঢ় ଶ͕มΘͬͨΒϦϏϧυͯ͠஋Λऔ ಘͰ͖ΔΑ͏ʹ͢Δ react-use
  84. react-hooks-testing-library test('should increment counter', () => { const { result

    } = renderHook(() => useCounter()) act(() => { result.current.increment() }) expect(result.current.count).toBe(1) }) ࣗ࡞ Hooks ͷςετΛॻ͘ʹ͸ίϯ ϙʔωϯτΛߋ৽͢ΔͨΊͷτϦ ΨʔΛॻ͍ͯ࠶ϨϯμϦϯάͤͨ͞ Γɺ஋Λߋ৽͢ΔͨΊͷίʔυΛॻ ͍ͨΓ͠ͳ͚Ε͹͍͚ͳ͔ͬͨ΋ͷ Λ؆୯ʹ͔͚ΔΑ͏ʹ͢Δ
  85. 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 ͷঢ়ଶΛ֬ೝ͢Δ ᶃ ᶄ ᶅ
  86. 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 ͸ͦΕ͘Β͍ ϘΠϥʔίʔυΛ࡟ݮͰ͖ΔϥΠϒϥϦ ᶃ ᶄ ᶅ
  87. flutter_use ͱ flutter_hooks_testing

  88. ·ͱΊ

  89. ·ͱΊ • ΫϥΠΞϯταΠυ͕શͯએݴత UI ͷํ޲ʹͳͬͯ͘Ε͓ͨ ͔͛Ͱ Flutter Ͱ࡞Δʹͯ͠΋ React ͔Βֶ΂ͯ

    Jetpack Compose Ͱ࡞Δʹͯ͠΋ࢀߟʹͳΔ΋ͷ͕ΰϩΰϩͱస ͕͍ͬͯΔ • ֤ݴޠͷҧ͍ͳΜͯࠣࡉͳ΋ͷͰ UI ϑϨʔϜϫʔΫΛͦΕͧ ΕֶͿͷ͕େม͚ͩͬͨͲɺ༏͍͠ੈքʹͳ͖ͬͯͨ
  90. Google Developers Expert @wasabeef_jp wasabeef CyberAgent, Inc.