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

実例と歴史から学ぶ_Flutterの状態管理方法の選定_.pdf

entaku
November 28, 2021

 実例と歴史から学ぶ_Flutterの状態管理方法の選定_.pdf

entaku

November 28, 2021
Tweet

More Decks by entaku

Other Decks in Technology

Transcript

  1. ࣮ྫͱྺ࢙͔ΒֶͿʂ


    Flutterͷঢ়ଶ؅ཧํ๏ͷબఆ
    FlutterKaigi 2021 11/29 19:45ʙ


    entaku / @entaku_0818

    View Slide

  2. • Name: ԕ౻୓໻ (entaku)


    • Twitter: @entaku_0818


    • Job: ϞόΠϧΞϓϦΤϯδχΞ


    • Android / Flutter / iOSͷܦݧ͋Γ


    • iOSΤϯδχΞͷܦݧ͕௕͍
    ࣗݾ঺հ

    View Slide

  3. Flutterྺ
    2019/4ϦϦʔε 2021/4ϦϦʔε(ϦϓϨΠε)

    View Slide

  4. 2019/4ϦϦʔε 2021/4ϦϦʔε(ϦϓϨΠε)
    StatefulWidget Provider
    Flutterྺ

    View Slide

  5. Flutterͷঢ়ଶ؅ཧԿ࢖͑͹͍͍͔Θ͔Βͳ͍
    😥

    View Slide

  6. iOSͷ࣌ࣗ෼͸ͲͷΑ͏ʹֶΜ͚ͩͬʁ
    🤔

    View Slide

  7. https://peaks.cc/books/iOS_architecture

    View Slide

  8. https://peaks.cc/books/iOS_architecture
    ͳͥͦͷઃܭ͕࠾༻͞Ε͍ͯΔͷ͔ʁ


    Λ࣮ྫͱྺ࢙ͷ؍఺͔Βॻ͔Ε͍ͯΔ

    View Slide

  9. ࠓճ๻΋͜ͷΑ͏ͳࢿྉΛ࡞Γ͍ͨʂ
    🔥

    View Slide

  10. Flutterঢ়ଶ؅ཧͷྺ࢙ͷ೉͠͞
    •Flutter ϦϦʔε౰ॳ(2018/12)͔Β3೥ऑ͔͠ܦͬͯͳ͍


    •ެࣜͰఏࣔ͞Ε͍ͯΔख๏͸͋Δ΋ͷͷ؅ཧख๏͸ͨ͘͞Μ͋Δ


    •10ݸҎ্ͷํ๏͕ఏࣔ͞Ε͍ͯΔ
    https://docs.
    fl
    utter.dev/development/data-and-backend/state-mgmt

    View Slide

  11. Flutterঢ়ଶ؅ཧͷͨ͘͞Μͷํ๏
    StatefulWidget
    Provider Riverpod
    InheritedWidget
    ScopedModel
    Redux
    Fish-Redux BLoC / Rx
    GetIt
    https://docs.
    fl
    utter.dev/development/data-and-backend/state-mgmt

    View Slide

  12. Flutterঢ়ଶ؅ཧͷͨ͘͞Μͷํ๏
    StatefulWidget
    Provider Riverpod
    InheritedWidget
    ScopedModel
    Redux
    Fish-Redux BLoC / Rx
    GetIt
    https://docs.
    fl
    utter.dev/development/data-and-backend/state-mgmt
    ͷதͰ΋ಛʹຊےͷྲྀΕ͕෼͔Γͦ͏ͳͱ͜ΖΛϐοΫΞοϓ

    View Slide

  13. Ͱ͸࣮ࡍʹͦΕͧΕͷίʔυΛݟ͍͖ͯ·͠ΐ͏

    View Slide

  14. ͦͷલʹ…

    View Slide

  15. Flutter is declarative

    View Slide

  16. https://
    fl
    utter.dev/docs/development/data-and-backend/state-mgmt/declarative
    Flutter is declarative


    =Flutter͸એݴతUIͰ͢
    Flutter is declarative is licensed under Creative Commons Attribution 4.0 International License,

    View Slide

  17. Sample CodeͷΠϝʔδ
    Football API
    APIΛୟ͘
    औಘͨ͠σʔλΛҰཡͰදࣔ
    https://github.com/entaku0818/football_
    fl
    utter

    View Slide

  18. Ͱ͸࣮ࡍʹͦΕͧΕͷίʔυΛݟ͍͖ͯ·͠ΐ͏

    View Slide

  19. StatefulWidget

    View Slide

  20. StatefulWidget
    •Flutter ϦϦʔε౰ॳ(2018/12)͔Β͋Δ


    •WidgetʹState͕ηοτʹͳ͍ͬͯΔ
    https://api.
    fl
    utter.dev/
    fl
    utter/widgets/StatefulWidget-class.html

    View Slide

  21. https://api.
    fl
    utter.dev/
    fl
    utter/widgets/StatelessWidget-class.html


    https://api.
    fl
    utter.dev/
    fl
    utter/widgets/StatefulWidget-class.html
    class GreenFrog extends StatelessWidget
    {

    const GreenFrog({ Key? key }) : super(key:
    key)
    ;

    @override
    Widget build(BuildContext context)
    {

    return Container(color: const
    Color(0xFF2DBD3A))
    ;

    }

    }
    class YellowBird extends StatefulWidget
    {

    const YellowBird({ Key? key }) : super(key: key)
    ;

    @override
    State createState() => _YellowBirdState()
    ;

    }

    class _YellowBirdState extends State
    {

    @override
    Widget build(BuildContext context)
    {

    return Container(color: const Color(0xFFFFE306))
    ;

    }

    }
    StatefulWidget - ެࣜͷࣄྫ

    View Slide

  22. class HomeScreen extends StatefulWidget
    {

    HomeScreen({Key key}) : super(key: key)
    ;

    ɹ// StateΛࢦఆ
    _HomeScreenState createState() => _HomeScreenState()
    ;

    }

    class _HomeScreenState extends State
    {

    ɹ
    ɹ// νʔϜҰཡΛఆ͍ٛͯ͠Δ
    List _teams = []
    ;

    void initState() { // StateͷॳظԽॲཧ
    super.initState()
    ;

    fetch(); // ը໘ΞΫηε࣌ʹσʔλΛऔಘͯ͘͠Δ
    }

    StatefulWidget - SampleCode

    View Slide

  23. @overrid
    e

    Widget build(BuildContext context)
    {

    return Scaffold
    (

    appBar: AppBar
    (

    title: const Text('νʔϜҰཡ')
    ,

    )
    ,

    body: ListView.builder
    (

    itemBuilder: (BuildContext context, int index)
    {

    return Card
    (

    child: ListTile
    (

    title: Text(_teams[index].name)
    ,

    )
    ,

    )
    ;

    }
    ,

    itemCount: _teams.length
    ,

    )
    ,

    )
    ;

    }
    Future> fetch() async
    {

    final _teamsRepository = TeamsRepository()
    ;

    final result = await _teamsRepository.feachTeams()
    ;

    result.when
    (

    success: (teams)
    {

    setState(()
    {

    _teams = teams
    ;

    })
    ;

    }
    ,

    failure: (error)
    {

    // Τϥʔॲཧ
    }
    ,

    )
    ;

    }
    StatefulWidget - SampleCode

    View Slide

  24. ϝϦοτ
    σϝϦοτ
    w σʔλΛ7JFXʹ࣋ͨͳ͚Ε͹ͳΒͳ͍
    w ࣄྫͰ͸νʔϜҰཡͷσʔλΛ8JEHFUͱಉ͡৔ॴʹఆٛ
    w ͋ΒΏΔॲཧ͕7JFXʹॻ͔ΕΔͷͰ'BU7JFXʹͳΔ
    w ࣄྫͰ͸νʔϜҰཡͷσʔλऔಘॲཧΛ8JEHFUͱಉ͡৔ॴʹఆٛ
    w Ұը໘Ͱॲཧ͕ॻ͚ΔͷͰ෼͔Γ΍͍͢
    StatefulWidget

    View Slide

  25. ScopedModel

    View Slide

  26. ScopedModel
    •2018/11 ʹversion 1


    •࠷ۙ͸ߋ৽͞Ε͍ͯͳ͍


    •WidgetͱModelͷ෼཭
    https://pub.dev/packages/scoped_model
    https://pub.dev/packages/scoped_model/example

    View Slide

  27. // Note: It must extend from Model.
    class CounterModel extends Model
    {

    int _counter = 0
    ;

    int get counter => _counter
    ;

    void increment()
    {

    // First, increment the counter
    _counter++
    ;



    // Then notify all the listeners.
    notifyListeners()
    ;

    }

    }
    ScopedModel - ެࣜͷࣄྫ
    ঢ়ଶΛ΋ͭ.PEFMΛఆٛ

    View Slide

  28. class CounterApp extends StatelessWidget
    {

    @override
    Widget build(BuildContext context)
    {

    // First, create a `ScopedModel` widget. This will provide
    // the `model` to the children that request it.
    return new ScopedModel
    (

    model: new CounterModel()
    ,

    child: new Column(children:
    [

    // Create a ScopedModelDescendant. This widget will get the
    // CounterModel from the nearest ScopedModel.
    // It will hand that model to our builder method, and rebuild
    // any time the CounterModel changes (i.e. after we
    // `notifyListeners` in the Model).
    new ScopedModelDescendant
    (

    builder: (context, child, model) => new Text('${model.counter}')
    ,

    )
    ,

    new Text("Another widget that doesn't depend on the CounterModel"
    )

    ]
    )

    )
    ;

    }

    }
    ScopedModel - ެࣜͷࣄྫ
    ར༻͢Δ
    4DPQFE.PEFMΛఆٛ
    .PEFMΛར༻͍ͨ͠8JEHFUΛ
    4DPQFE.PEFM%FTDFOEBOUͰ
    แΉ

    View Slide

  29. class ScopedModelHome extends StatelessWidget
    {

    @overrid
    e

    Widget build(BuildContext context)
    {

    // StatelessWidgetͰఆٛ͠ModelΛݺͼग़͢=> ViewʹϏδωεϩδοΫ͕ೖͬͯ͜ͳ͍
    return ScopedModel
    (

    model: TeamScopedModel()
    ,

    child: ScopedModelDescendant
    (

    // ScopedModelDescendant഑ԼͰϞσϧΛࢀর
    builder: (context, child, model) => Scaffold
    (

    appBar: AppBar
    (

    title: const Text('νʔϜҰཡ')
    ,

    )
    ,

    drawer: Header()
    ,

    body: ListView.builder
    (

    itemBuilder: (BuildContext context, int index)
    {

    return Card
    (

    child: ListTile
    (

    title: Text(model.teams[index].name)
    ,

    )
    ,

    )
    ;

    }
    ,

    itemCount: model.teams.length
    ,

    )
    ,

    )
    ,

    )
    ,

    )
    ;

    }

    }
    ScopedModel - SampleCode

    View Slide

  30. class TeamScopedModel extends Model
    {

    List _teams = []
    ;

    List get teams => _teams
    ;

    TeamScopedModel()
    {

    // ॳճ࣮ߦ࣌ʹσʔλऔಘΛ࣮ߦ
    fetch()
    ;

    }

    Future> fetch() async
    {

    final _teamsRepository = TeamsRepository()
    ;

    final result = await _teamsRepository.feachTeams()
    ;

    result.when
    (

    success: (teams)
    {

    _teams = teams
    ;

    // σʔλߋ৽࣌ʹΠϕϯτൃՐ
    notifyListeners()
    ;

    }
    ,

    failure: (error)
    {

    // Τϥʔॲཧ
    }
    ,

    )
    ;

    }

    }

    ScopedModel - SampleCode

    View Slide

  31. ϝϦοτ
    σϝϦοτ
    w ࠷ޙͷߋ৽͕
    w ·ͩ/VMM4BGFUZʹ΋ରԠ͍ͯ͠ͳ͍
    w ࠓޙߋ৽͞ΕΔՄೳੑ͸௿͍ʁ
    w
    w 4UBUFGVM8JEHFUͱൺֱͯ͠ϏδωεϩδοΫΛ෼཭͠΍͍͢
    ScopedModel - SampleCode

    View Slide

  32. Provider

    View Slide

  33. https://pub.dev/packages/provider
    •2018/10 ver1.0.0


    •͜ͷ࣌ظʹ࢖ͬͯͨਓ͍Δͷ͔ͳ..


    •ެࣜαΠτͰਪ঑͞Ε͍ͯΔ΍Γํ
    https://docs.
    fl
    utter.dev/development/data-and-backend/state-mgmt/simple


    https://pub.dev/packages/provider
    Provider

    View Slide

  34. void main()
    {

    runApp
    (

    ChangeNoti
    fi
    erProvider
    (

    create: (context) => CartModel(), // ChangeNoti
    fi
    e
    r

    child: const MyApp(), // Widge
    t

    )
    ,

    )
    ;

    }
    Provider - ެࣜͷࣄྫ
    $IBOHF/PUJ
    fi
    FS1SPWJEFS
    Ͱ$IBOHF/PUJ
    fi
    FSͱ8JEHFUΛ
    ఆٛ

    View Slide

  35. class CartModel extends ChangeNoti
    fi
    er
    {

    /// Internal, private state of the cart.
    fi
    nal List _items = []
    ;

    /// An unmodi
    fi
    able view of the items in the cart.
    Unmodi
    fi
    ableListView get items => Unmodi
    fi
    ableListView(_items)
    ;

    /// The current total price of all items (assuming all items cost $42).
    int get totalPrice => _items.length * 42
    ;

    /// Adds [item] to cart. This and [removeAll] are the only ways to modify the
    /// cart from the outside.
    void add(Item item)
    {

    _items.add(item)
    ;

    // This call tells the widgets that are listening to this model to rebuild.
    notifyListeners()
    ;

    }

    /// Removes all items from the cart.
    void removeAll()
    {

    _items.clear()
    ;

    // This call tells the widgets that are listening to this model to rebuild.
    notifyListeners()
    ;

    }

    }
    Provider - ެࣜͷࣄྫ
    $IBOHF/PUJ
    fi
    FSͰ஋Λఆٛ

    View Slide

  36. return Consumer
    (

    builder: (context, cart, child)
    {

    return Text("Total price: ${cart.totalPrice}")
    ;

    }
    ,

    );
    Provider - ެࣜͷࣄྫ
    $POTVNFSͰғ͏͜ͱͰ
    $IBOHF/PUJ
    fi
    FSൃՐ࣌ʹ
    8JEHFUΛߋ৽

    View Slide

  37. Provider - SampleCode
    '/changeNotifier': (BuildContext context) => ChangeNotifierProvider
    (

    create: (context) => TeamModel(),ɹ// ChangeNotifie
    r

    child: ChangeNotifierHome(), // Widge
    t

    )
    ,

    View Slide

  38. Provider - SampleCode
    class ChangeNotifierHome extends StatelessWidget
    {

    @overrid
    e

    Widget build(BuildContext context)
    {

    return Scaffold
    (

    appBar: AppBar
    (

    title: const Text('νʔϜҰཡ')
    ,

    )
    ,

    drawer: Header()
    ,

    // Widget಺ͷߋ৽ൣғΛConsumerͰғ͏
    body: Consumer
    (

    builder: (BuildContext context, TeamModel value, Widget child)
    {

    return ListView.builder
    (

    itemBuilder: (BuildContext context, int index)
    {

    return Card
    (

    child: ListTile
    (

    title: Text(value.teams[index].name)
    ,

    )
    ,

    )
    ;

    }
    ,

    itemCount: value.teams.length
    ,

    )
    ;

    }))
    ;

    }

    }

    View Slide

  39. Provider - SampleCode
    class TeamModel extends ChangeNotifier
    {

    List _teams = []
    ;

    List get teams => _teams
    ;

    TeamModel()
    {

    // ॳظԽ࣌ʹσʔλऔಘ
    fetch()
    ;

    }

    Future> fetch() async
    {

    final _teamsRepository = TeamsRepository()
    ;

    final result = await _teamsRepository.feachTeams()
    ;

    result.when
    (

    success: (teams)
    {

    _teams = teams
    ;

    //ɹมߋΛ௨஌
    notifyListeners()
    ;

    }
    ,

    failure: (error)
    {

    //ɹΤϥʔॲཧ
    }
    ,

    )
    ;

    }

    }

    View Slide

  40. Provider
    w ෳ਺ͷ1SPWJEFSͱ8JEHFUͷ૊Έ߹ΘͤΛར༻͢Δ৔߹ ը໘਺͕ଟ͍ෳࡶͳը
    ໘ભҠ
    ʹΤϥʔʹͳͬͯ͠·͏
    ϝϦοτ
    σϝϦοτ
    w 1SPWJEFSͱ8JEHFUͷ૊Έ߹Θͤґଘੑͷ஫ೖͱঢ়ଶ؅ཧ͕ߦ͑Δ
    '/changeNotifier': (BuildContext context) => ChangeNotifierProvider
    (

    create: (context) => TeamModel()
    ,

    child: ChangeNotifierHome()
    ,

    )
    ,

    View Slide

  41. Riverpod

    View Slide

  42. https://pub.dev/packages/provider
    •2021/11/5ʹ ver1.0.0


    •Providerͷ໰୊఺Λղফ͢ΔܗͰ஀ੜ
    https://pub.dev/packages/riverpod


    https://riverpod.dev
    RiverPod

    View Slide

  43. fi
    nal counterProvider = StateNoti
    fi
    erProvider((ref)
    {

    return Counter()
    ;

    })
    ;

    class Counter extends StateNoti
    fi
    er
    {

    Counter(): super(0)
    ;

    void increment() => state++
    ;

    }
    Riverpod - ެࣜͷࣄྫ
    άϩʔόϧʹ1SPWJEFSΛఆٛ

    View Slide

  44. class Example extends ConsumerWidget
    {

    @override
    Widget build(BuildContext context, WidgetRef ref)
    {

    fi
    nal count = ref.watch(counterProvider)
    ;

    return Text(count.toString())
    ;

    }

    }
    Riverpod - ެࣜͷࣄྫ
    $POTVNFS8JEHFUͰ8JEHFUΛੜ੒
    ͠ɺ
    SFGXBUDIͰ1SPWJEFSͷঢ়ଶΛ؅ཧ

    View Slide

  45. Riverpod
    // ProviderScopeͰର৅ͷWidgetΛғ͏
    '/RiverpodHome': (BuildContext context) => ProviderScope
    (

    child: RiverpodHome()
    ,

    )

    View Slide

  46. Riverpod
    // TeamStateNotifierΛࢀর͠ɺάϩʔόϧʹެ։
    final TeamStateNotifierProvider
    =

    StateNotifierProvider>
    (

    (ref) => TeamStateNotifier([])
    ,

    )
    ;

    class TeamStateNotifier extends StateNotifier>
    {

    TeamStateNotifier(List state) : super(state)
    {

    // ॳظԽ࣌ʹσʔλऔಘ
    _fetch()
    ;

    }

    Future> _fetch() async
    {

    final _teamsRepository = TeamsRepository()
    ;

    final result = await _teamsRepository.feachTeams()
    ;

    result.when
    (

    success: (teams)
    {

    state = teams
    ;

    }
    ,

    failure: (error)
    {

    // Τϥʔॲཧ
    }
    ,

    )
    ;

    }

    }

    View Slide

  47. Riverpod
    class RiverpodHome extends ConsumerWidget
    {

    @overrid
    e

    Widget build(BuildContext context, WidgetRef ref)
    {

    // ref.watchͰProviderͷঢ়ଶΛࢀর
    final teams = ref.watch(TeamStateNotifierProvider)
    ;

    return Scaffold
    (

    appBar: AppBar
    (

    title: const Text('νʔϜҰཡ')
    ,

    )
    ,

    drawer: Header()
    ,

    body: ListView.builder
    (

    itemBuilder: (BuildContext context, int index)
    {

    return Card
    (

    child: ListTile
    (

    title: Text(teams[index].name)
    ,

    )
    ,

    )
    ;

    }
    ,

    itemCount: teams.length
    ,

    )
    ,

    )
    ;

    }

    }

    View Slide

  48. Riverpod
    ϝϦοτ
    σϝϦοτ
    w 1SPWJEFSΛάϩʔόϧͰఆٛՄೳͰͲͷ8JEHFU͔Β΋࢖͑Δ
    w ແཧ໼ཧ͋͛ΔͳΒɺ
    ϦϦʔεͨ͠͹͔ΓͰมߋͷՄೳੑ͕͋Δ
    w 1SPWJEFS͸WFSTJPO·Ͱग़͍ͯΔ

    View Slide

  49. • ·ͣγϯϓϧͳΞϓϦΛ࡞ΔͳΒStatefulWidget͕͍͍


    • ܦݧऀ΋ଟ͍ͷͰ࣮ྫ΋͋Δ͸ͣ


    • ScopedModel͸ߋ৽͞Εͯͳ͍Α͏ͩ͠ࠓޙ͸࢖͏΂͖Ͱ͸ͳ
    ͦ͞͏


    • ෳ਺ը໘Ͱঢ়ଶΛڞ༗͢Δ৔߹͸Provider΍RiverpodΛ࢖༻͢Δ


    • ҆ఆੑ͕ཉ͍͠ͳΒProvider


    • ը໘ભҠ͕ෳࡶͳΒRiverpod
    ·ͱΊ

    View Slide

  50. ΈΜͳ͸Կ࢖͍ͬͯΔΜͩΖ͏ʁ
    🤔

    View Slide

  51. ΞϯέʔτͱͬͯΈ·ͨ͠ʂ


    11/19࣌఺ 19ճ౴


    https://docs.google.com/forms/d/e/
    1FAIpQLSccB2iZJ78FeLPj1ST31FVUxj73Tc4d-0KhXpbJnT-l9kYZMQ/viewform

    View Slide

  52. ݩʑωΠςΟϒ։ൃऀ͕໿7ׂ


    Flutter͔Β͸3ׂ

    View Slide

  53. શͯͷਓ͕StatefulWidgetΛ࢖ͬͯͨ


    BLoC΍Redux͸ͦΜͳʹ࢖ΘΕ͍ͯͳ͍ʁ

    View Slide

  54. StatefulWidget͸


    গͣͭ͠࢖ΘΕͳ͘ͳ͖͍ͬͯͯΔ


    Riverpod͕த৺͔ʁ

    View Slide

  55. ࠓޙ͸RiverpodΛ࢖͍͖͍ͬͯͨਓ͕ଟ਺

    View Slide

  56. ࣮ྫͱྺ࢙͔ΒֶͿʂ
    Flutterͷঢ়ଶ؅ཧํ๏ͷ
    બఆ

    View Slide

  57. ࣮ྫͱྺ࢙͔ΒֶͿʂ
    Flutterͷঢ়ଶ؅ཧํ๏ͷ
    બఆ
    ʴະདྷ

    View Slide

  58. https://speakerdeck.com/aomathwift/ji-neng-gotonidong-zuo-
    suruminiapuridepurebiyusaikuruwobao-su-nisitahua
    ઌ೔ͷiOSDCͰ͋ͬͨϛχΞϓϦͷ࿩
    https://speakerdeck.com/aomathwift/ji-neng-gotonidong-zuo-
    suruminiapuridepurebiyusaikuruwobao-su-nisitahua

    View Slide

  59. ઌ೔ͷiOSDCͰ͋ͬͨϛχΞϓϦͷ࿩
    https://techlife.cookpad.com/entry/2021/06/16/110000

    View Slide

  60. কདྷతʹ
    StatefulWidget
    γϯϓϧͳΞϓϦΛ࡞Δ


    (ը໘಺Ͱ׬݁)
    Provider
    ෳࡶͳΞϓϦΛ࡞Γ͍ͨ


    ଟ͘ͷը໘ભҠ͕͋Δ
    Riverpod ?
    ϚϧνϞδϡʔϧ
    Խͯ͠ϛχΞϓϦ
    Λ࡞Δ

    View Slide

  61. Ξϯέʔτͷ݁Ռ͔Β΋ࠓޙ΋ͬͱ
    ΋ͬͱFlutterͰ࡞ΔΞϓϦͷෳࡶ͞͸
    ૿͍ͯ͘͠ͷͰ͸ʁ🤔

    View Slide

  62. ϗϯτͷ·ͱΊ
    • ·ͣγϯϓϧͳΞϓϦΛ࡞ΔͳΒStatefulWidget͕͍͍


    • ܦݧऀ΋ଟ͍ͷͰ࣮ྫ΋͋Δ͸ͣ


    • ScopedModel͸ߋ৽͞Εͯͳ͍Α͏ͩ͠ࠓޙ͸࢖͏΂͖Ͱ͸ͳ
    ͦ͞͏


    • ෳ਺ը໘Ͱঢ়ଶΛڞ༗͢Δ৔߹͸Provider΍RiverpodΛ࢖༻͢Δ


    • ҆ఆੑ͕ཉ͍͠ͳΒProvider


    • ը໘ભҠ͕ෳࡶͳΒRiverpod


    • (iOS։ൃͷࣄྫ͔Β)ϚϧνϞδϡʔϧԽͯ͠ϛχΞϓϦΛ࡞Δ͜ͱ
    ͕ٻΊΒΕΔΑ͏ʹͳΔՄೳੑ

    View Slide

  63. ࢀߟ
    • Flutter SDKެࣜαΠτ- https://api.
    fl
    utter.dev/


    • Flutter Developer ެࣜυΩϡϝϯτ - https://
    fl
    utter.dev/development


    • iOSΞϓϦઃܭύλʔϯೖ໳ - https://peaks.cc/books/iOS_architecture


    • iOSDC ػೳ͝ͱʹಈ࡞͢ΔϛχΞϓϦͰϓϨϏϡʔαΠΫϧΛര଎ʹͨ͠࿩
    - https://speakerdeck.com/aomathwift/ji-neng-gotonidong-zuo-
    suruminiapuridepurebiyusaikuruwobao-su-nisitahua


    • Flutterͷঢ়ଶ؅ཧख๏ͷબఆ - https://medium.com/
    fl
    utter-jp/
    state-1daa7fd66b94


    • ίʔυੜ੒Λ༻͍ͨiOSΞϓϦϚϧνϞδϡʔϧԽͷͨΊͷґଘղܾ -
    https://techlife.cookpad.com/entry/2021/06/16/110000


    • Flutter Ͱ࡞ΒΕͨ༑ਓͷΞϓϦ - ⭐ https://github.com/bannzai/Pilll ⭐

    View Slide

  64. ϑΟʔυόοΫ͍ͩ͘͞ʂ

    View Slide

  65. ࣮ྫͱྺ࢙͔ΒֶͿʂ


    Flutterͷঢ়ଶ؅ཧํ๏ͷબఆ
    FlutterKaigi 2021 11/29 19:45ʙ


    entaku / @entaku_0818

    View Slide