First of all, of course, you can look at the official document translation reference

Why is Provider management state needed

Data changes, data sharing, need providers

  • The code for Flutter, yesResponsive/declarative. The old Android /iOS code, yesimperative.
  • responsiveCode, basically all need to be carried outState managementIt can also be understood thatData sharing.
  • The interface, the data is changing, it needs to be managed,simpleIt is better to manage the widgets directly in the StatefulWidget, but more complicated to manage the widgets with providers and the like.

Examples of simple and complex data

How simple is a change in the data? — Such as the current page in a PageView component, the current progress in a complex animation, the currently selected TAB in a BottomNavigationBar. These are in the widget tree, and other parts do not need to access this state. There is no need to serialize the state, and the state does not change in complex ways.

What data changes do Privider need to manage? For example, user options, login information, notifications in a social app, shopping cart in an e-commerce app, read/unread article status in a news app.

.

Flutter state management includes Redux, Rx, hooks, ScopedModel, and Provider, which is officially recommended.

If you don’t know anything else, it must be the official recommendation first.

Second, the use of Provider

Well, providers are officially recommended. Unfamiliar, can look at these two first.

Provider official article

Use a Provider to manage the status of the Flutter application


Ii.1 Operation Procedure

The introduction of the provider

dependencies:
  provider: ^3.1. 0
Copy the code

There are three simple steps to using a provider:

  • Create shared classes that inherit from ChangeNotifier
  • Set up the data
  • Get data in two ways: provider.of (context) and Consumer

Very simple ~

.

The simplest example isProvider.of (context)

The following code:

  • Create a shared class, add a method that grows the data, and refresh on call
  • Call the data
  • Build is called again to refresh the UI

import 'package:flutter/material.dart';

import 'package:provider/provider.dart';
import 'package:flutter/foundation.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    // Create widgets that hold CounterNotifier data
    return ChangeNotifierProvider.value(
      value: CounterNotifier(),
      child: MaterialApp(
        title: 'Privoder Demo',
        theme: ThemeData(
          primarySwatch: Colors.blue,
        ),
        home: ProvidePage(title: 'Provider Test page '),),); }}class ProvidePage extends StatelessWidget {
  final String title;

  ProvidePage({Key key, this.title}) : super(key: key);

  @override
  Widget build(BuildContext context) {

    // Get CounterNotifier data (the simplest way)
    final counter = Provider.of<CounterNotifier>(context);

    return Scaffold(
      appBar: AppBar(
        title: Text(title),
      ),
      body: Center(
        child: Column(
          mainAxisSize: MainAxisSize.min,
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text(
              'Press the button to make the number grow :',
            ),
            Text(
              '${counter.count}',
              style: Theme.of(context).textTheme.display1,
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () {
          counter.increment();
        },
        tooltip: 'Increment',
        child: constIcon(Icons.add), ), ); }}// Core: inherited from ChangeNotifier
// This type of file should be attached to a separate class file
class CounterNotifier with ChangeNotifier {
  int _count = 0;
  int get count => _count;

  increment() {
    _count++;
    // The core method notifies the UI refresh and calls the build methodnotifyListeners(); }}Copy the code

.

Effect:

Pay attention to

  • Using provider. of When notifyListeners are called in the ChangeNotifier, the build in the Widget is called again each time

That’s about it. You might say, well, setState. No, this is definitely different. SetState is so inflexible.

.

2.3 Example Consumer mode

Example: Set a value on page 1 and display it on page 2 (don’t ask why you don’t use Navigator directly, demo, just demo)

import 'package:flutter/material.dart';
import 'package:provider/provider.dart';

main() {
  runApp(ChangeNotifierProvider<CounterNotifier>.value(
    value: CounterNotifier(),
    child: MyApp(),
  ));
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    return MultiProvider(
      providers: [
        Provider.value(value: 36),
        ChangeNotifierProvider.value(value: CounterNotifier())
      ],
      child: MaterialApp(
        title: 'Privoder Demo', theme: ThemeData( primarySwatch: Colors.blue, ), home: Page1(), ), ); }} class Page1 extends StatelessWidget {@override Widget Build (BuildContext Context) {// Get text size final size = Provider.of<int>(context).toDouble(); Final counter = Provider. Of <CounterNotifier>(context); // Output when calling buildprint('rebuild page 1');
    return Scaffold(
      appBar: AppBar(
        title: Text('Page1'),), body: Center (child: the Column (mainAxisAlignment: mainAxisAlignment Center, children: < widgets > [/ / show the count Text ('Current count: ${counter.count}', // Set text size style: TextStyle(fontSize: size,), SizedBox(height: 50,), // jump Page2 RaisedButton(onPressed: () => Navigator.of(context).push( MaterialPageRoute(builder: (context) => Page2()), ), child: Text('Next'),),),),); } } class Page2 extends StatelessWidget { @override Widget build(BuildContext context) {print('rebuild page 2');
    return Scaffold(
      appBar: AppBar(
        title: Text('Page2'),
      ),
      body: Center(
        child: Consumer2<CounterNotifier, int>(
            builder: (context, counter, size, _) {
              print('rebuild page 2 refresh count');

              return Column(
                mainAxisSize: MainAxisSize.min,
                mainAxisAlignment: MainAxisAlignment.center,
                children: <Widget>[
                  Text(
                    'You have pushed the button this many times:',
                  ),
                  Text(
                    '${counter.count}', style: TextStyle( fontSize: size.toDouble(), ), ), ], ); }),), floatingActionButton: floatingActionButton (onPressed: () {falseBuild) Provider. Of <CounterNotifier>(context, listen:false).increment();
        },
        tooltip: 'Increment',
        child: const Icon(Icons.add),
      ),
    );
  }
}


class CounterNotifier with ChangeNotifier {
  int _count = 0;

  int get count => _count;

  increment() { _count++; notifyListeners(); }}Copy the code

.

Pay attention to

  • 1, Inside Page2, use Consumer
  • If Provider. Of’s listen is false, build will not be called again

Set the value on page 2. When page 1 is returned, the value of page 2 is displayed on page 1

.

.

contrast
  • Provider. Of: If you just need to get the data model,You don't need to listen for changesIt is recommended to use Provider. Of (context, listen: false) to retrieve the data model.
  • Listener (Consumer recommended) : Consumer is recommended.

.

END

Reference: Flutter start dry series – State Management Provider3