title: Clarification about provider in Flutter - How to save data
body: <p>I'm new to <code>Flutter</code> and I'm spending some time about provider patter, I'm a PHP guy so I have a basic knowledge about it works, especially in <code>Laravel</code> framework.<br />
  For me a provider is something that should manage data, retrive it from a DB, manipulate ad save.</p>
  <p>As far as I understand the concept is the same in flutter, but is quite difficult follow the docs.</p>
  <p>I have created a simple app that call a REST API and now I'd like to add the response to my provider to use the data in all my pages and widgets.</p>
  <p>Here my code.</p>
  <p>The <code>splash.dart</code> file that show a splashscreen to my user and call the external endpoint, <em>here</em> I'd like to get my data and add to the provider.</p>
  <pre><code>import 'package:flutter/material.dart';
  import 'package:provider/provider.dart';
  
  import 'models/maison.dart';
  import 'dart:convert' as convert;
  import 'package:http/http.dart' as http;
  
  class SplashApp extends StatefulWidget {
    final VoidCallback onInitializationComplete;
  
    const SplashApp({
      Key key,
      @required this.onInitializationComplete,
    }) : super(key: key);
  
    @override
    _SplashAppState createState() =&gt; _SplashAppState();
  }
  
  class _SplashAppState extends State&lt;SplashApp&gt; {
    @override
    void initState() {
      super.initState();
      _initializeAsyncDependencies();
    }
  
    Future&lt;void&gt; _initializeAsyncDependencies() async {
      var url = 'https://run.mocky.io/v3/95237af1-b13f-4756-b308-56c9aac93c7e';
  
      // Await the http get response, then decode the json-formatted response.
      var response = await http.get(url);
      if (response.statusCode == 200) {
        var jsonResponse = convert.jsonDecode(response.body);
        var data = jsonResponse['data'];
        var name = data[0]['name'];
        print('Name: $name.');
      } else {
        print('Request failed with status: ${response.statusCode}.');
      }
      // &gt;&gt;&gt; initialize async dependencies &lt;&lt;&lt;
      // &gt;&gt;&gt; register favorite dependency manager &lt;&lt;&lt;
      // &gt;&gt;&gt; reap benefits &lt;&lt;&lt;
      Future.delayed(
        Duration(milliseconds: 3000),
        () =&gt; widget.onInitializationComplete(),
      );
    }
  
    @override
    Widget build(BuildContext context) {
      return MaterialApp(
        debugShowCheckedModeBanner: false,
        title: 'Splash Screen',
        theme: ThemeData(
          accentColor: Colors.black,
        ),
        home: _buildBody(),
      );
    }
  
    Widget _buildBody() {
      return Scaffold(
        body: Stack(
          fit: StackFit.expand,
          children: &lt;Widget&gt;[
            Container(
              decoration: BoxDecoration(
                color: Color(0xFFDDCDC8),
              ),
            ),
            Column(
              mainAxisAlignment: MainAxisAlignment.start,
              children: &lt;Widget&gt;[
                Expanded(
                  flex: 2,
                  child: Container(
                    child: Column(
                      mainAxisAlignment: MainAxisAlignment.center,
                      children: &lt;Widget&gt;[
                        CircleAvatar(
                          backgroundColor: Colors.white,
                          radius: 80.0,
                          child: Icon(
                            Icons.access_time,
                            color: Colors.black,
                            size: 80.0,
                          ),
                        ),
                        Padding(
                          padding: EdgeInsets.only(
                            top: 10.0,
                          ),
                        ),
                        Text(
                          'Title',
                          style: TextStyle(
                            fontWeight: FontWeight.bold,
                            fontSize: 26.0,
                          ),
                        ),
                        SizedBox(
                          height: 16.0,
                        ),
                        Text(
                          'Subtitle',
                          style: TextStyle(
                            fontSize: 16.0,
                          ),
                        ),
                      ],
                    ),
                  ),
                ),
                Expanded(
                  flex: 1,
                  child: Column(
                    mainAxisAlignment: MainAxisAlignment.center,
                    children: &lt;Widget&gt;[
                      CircularProgressIndicator(),
                      Padding(
                        padding: EdgeInsets.only(top: 20.0),
                      ),
                      Text('Caricamento'),
                    ],
                  ),
                ),
              ],
            )
          ],
        ),
      );
    }
  }
  </code></pre>
  <p>Here's my <code>main.dart</code> file, here I init my tabs and some stuff. I have added there the <code>ChangeNotifyer</code> because here I need the data, maybe is not the right place?</p>
  <pre><code>import 'package:testapp/localization/app_localization.dart';
  import 'package:testapp/pages/home.dart';
  import 'package:testapp/pages/maison.dart';
  import 'package:testapp/pages/map.dart';
  import 'package:testapp/splash.dart';
  import 'package:flutter/foundation.dart';
  import 'package:flutter/material.dart';
  import 'package:flutter/services.dart';
  import 'package:flutter_localizations/flutter_localizations.dart';
  import 'package:google_fonts/google_fonts.dart';
  import 'package:provider/provider.dart';
  import 'package:testapp/providers/maisons_provider.dart';
  
  void main() {
    LicenseRegistry.addLicense(() async* {
      final license = await rootBundle.loadString('google_fonts/OFL.txt');
      yield LicenseEntryWithLineBreaks(['google_fonts'], license);
    });
  
    runApp(
      SplashApp(
        key: UniqueKey(),
        onInitializationComplete: () =&gt; runMainApp(),
      ),
    );
  }
  
  void runMainApp() {
    runApp(
      MyApp(),
    );
  }
  
  class MyApp extends StatelessWidget {
    @override
    Widget build(BuildContext context) {
      final textTheme = Theme.of(context).textTheme;
  
      return ChangeNotifierProvider(
        builder: (ctx) =&gt; MaisonsProvider(),
        child: MaterialApp(
          debugShowCheckedModeBanner: false,
          title: 'Title',
          theme: ThemeData(
            primaryColor: Colors.black,
            scaffoldBackgroundColor: Color(0xFFDDCDC8),
            visualDensity: VisualDensity.adaptivePlatformDensity,
            textTheme: GoogleFonts.montserratTextTheme(textTheme).copyWith(
              headline1: GoogleFonts.montserrat(
                textStyle: textTheme.headline1,
                fontSize: 30,
                fontWeight: FontWeight.w600,
                color: Colors.black,
              ),
              headline2: GoogleFonts.montserrat(
                textStyle: textTheme.headline1,
                fontSize: 22,
                fontWeight: FontWeight.w500,
                color: Colors.black,
              ),
              bodyText1: GoogleFonts.montserrat(
                textStyle: textTheme.bodyText1,
                color: Colors.black,
                fontWeight: FontWeight.w400,
                fontSize: 19,
              ),
            ),
          ),
          home: BottomBar(),
          routes: {
            MaisonPage.routeName: (ctx) =&gt; MaisonPage(),
          },
          supportedLocales: [
            Locale('en', 'US'),
            Locale('it', 'IT'),
          ],
          localizationsDelegates: [
            AppLocalizations.delegate,
            GlobalMaterialLocalizations.delegate,
            GlobalWidgetsLocalizations.delegate,
          ],
        ),
      );
    }
  }
  
  class BottomBar extends StatefulWidget {
    @override
    _BottomBarState createState() =&gt; _BottomBarState();
  }
  
  class _BottomBarState extends State&lt;BottomBar&gt; {
    int _currentIndex = 0;
  
    final List&lt;Widget&gt; _children = [
      HomePage(),
      MapPage(),
    ];
  
    void onTabTapped(int index) {
      setState(() {
        _currentIndex = index;
      });
    }
  
    @override
    Widget build(BuildContext context) {
      return Scaffold(
        body: _children[_currentIndex],
        bottomNavigationBar: BottomNavigationBar(
          backgroundColor: Color(0xFFDDCDC8),
          currentIndex: _currentIndex,
          onTap: onTabTapped,
          items: [
            BottomNavigationBarItem(
              icon: Icon(Icons.list),
              title: Text(
                AppLocalizations.of(context).translate('tab_maisons'),
              ),
            ),
            BottomNavigationBarItem(
              icon: Icon(
                Icons.map,
              ),
              title: Text(
                AppLocalizations.of(context).translate('tab_map'),
              ),
            ),
          ],
        ),
      );
    }
  }
  </code></pre>
  <p>This is my Maison model.</p>
  <pre><code>import 'package:testapp/models/point.dart';
  import 'package:flutter/material.dart';
  
  class Maison {
    final String id;
    final String name;
    final String imageUrl;
    final String price;
    final Point coordinates;
  
    Maison({
      @required this.id,
      @required this.name,
      @required this.price,
      @required this.imageUrl,
      @required this.coordinates,
    });
  }
  </code></pre>
  <p>And here's the provider:</p>
  <pre><code>import 'package:testapp/models/point.dart';
  import 'package:flutter/material.dart';
  import '../models/maison.dart';
  
  class MaisonsProvider with ChangeNotifier {
    // Questa lista è privata, non può essere recuperata dall'esterno, serve un getter
    List&lt;Maison&gt; _items = [
      Maison(
        id: '1',
        name: 'Prova 1',
        price: '60€',
        imageUrl:
            'https://images.unsplash.com/photo-1495562569060-2eec283d3391?ixlib=rb-1.2.1&amp;ixid=eyJhcHBfaWQiOjEyMDd9&amp;auto=format&amp;fit=crop&amp;w=1500&amp;q=80',
        coordinates: Point(
          lat: 45.4640976,
          lng: 9.1897378,
        ),
      ),
      Maison(
        id: '2',
        name: 'Prova 2',
        price: 'Free',
        imageUrl:
            'https://images.unsplash.com/photo-1582559934353-2e47140e7501?ixlib=rb-1.2.1&amp;ixid=eyJhcHBfaWQiOjEyMDd9&amp;auto=format&amp;fit=crop&amp;w=1788&amp;q=80',
        coordinates: Point(
          lat: 45.4640976,
          lng: 10.1897378,
        ),
      ),
      Maison(
        id: '3',
        name: 'Prova 3',
        price: 'Free',
        imageUrl:
            'https://images.unsplash.com/photo-1553355617-f7342d67a95f?ixlib=rb-1.2.1&amp;ixid=eyJhcHBfaWQiOjEyMDd9&amp;auto=format&amp;fit=crop&amp;w=1500&amp;q=80',
        coordinates: Point(
          lat: 45.9,
          lng: 10.1897378,
        ),
      ),
      Maison(
        id: '4',
        name: 'Prova 4',
        price: '40€',
        imageUrl:
            'https://images.unsplash.com/photo-1555141816-810dd5692b6a?ixlib=rb-1.2.1&amp;ixid=eyJhcHBfaWQiOjEyMDd9&amp;auto=format&amp;fit=crop&amp;w=1789&amp;q=80',
        coordinates: Point(
          lat: 46.4640976,
          lng: 9.30,
        ),
      ),
    ];
  
    // Getter
    // fa in modo che venga ritornata la lista di Maison,
    // non è la lista originale ma una copia.
    List&lt;Maison&gt; get items {
      return [..._items];
    }
  
    // Aggiunge una nuova Maison alla lista.
    // è importante passare dal provider così che sia lui a informare gli altri widget
    // che c'è stato un cambiamento
    void addMaison(Maison maison) {
      _items.add(maison);
  
      // Informa tutti i widget che sono interessati che c'è una nuova maison
      // in questo modo i widget possono fare una rebuild e mostrare i dati corretti
      notifyListeners();
    }
  }
  </code></pre>
  <p>I have added a <code>addMaison</code> method that should be the responsable to add a new Maison to my <code>_item</code> and a getter to retrive a copy of it.</p>
  <p>I have tried to init my provider in splash.dart in this way:</p>
  <pre><code>final maisonsData = Provider.of&lt;MaisonsProvider&gt;(context);
  Maison m = Maison(
      id: '1',
      name: 'Prova add',
      imageUrl: 'https://upload.wikimedia.org/wikipedia/commons/1/17/Google-flutter-logo.png',
      coordinates: {
          lat: 23,
          lng: 23,
      }
  );
  maisonData.addMaison(m);
  </code></pre>
  <p>and I tried to add it in my <code>_initializeAsyncDependencies</code> but the apps keep showing the splashscreen and can't continue.<br />
  How can I use the provider along the http request?</p>