introduce

Provider is a community-built state management package, not introduced by Google. However, Provider is one of the highly recommended state management methods by Google. It encapsulates InheritedWidget components to make them easier to use and reuse.

Before you start this chapter, you should know the following:

  • Familiar with DART language
  • Familiarize yourself with the basic components of FLUTTER
  • Understand InheritedWidget
  • Understand ChangeNotifier

If you haven’t used InheritedWidget before, we recommend that you do. You can use the InheritedWidget link to view and follow the source code analysis video provided in the InheritedWidget

Video Tutorial Address

Video Tutorial Address

The Provider edge

Why do we use a Provider instead of using an InheritedWidget directly

  • Simplified resource allocation and disposal
  • Lazy loading
  • Reduce a lot of template code when creating new classes
  • Support DevTools
  • A more general way of calling InheritedWidget (refer to the Provider. Of/Consumer/Selector)
  • Improved class extensibility, the overall listening architecture time complexity increases exponentially (e.g. ChangeNotifier, O(N))

Provider class structure diagram

Provider class description

Nested components

  • Nested: Simplified tree structures are deeply Nested
  • SingleChildWidget:A component of a single subcomponent, but it is associated withProxyWidgetDifferent, there is onebuildMethods.
  • SingleChildStatelessWidget:It’s an implementationSingleChildWidgettheStatelessWidget, must be usedbuildWithChildBuilding child components
  • SingleChildStatefulWidget:It’s an implementationSingleChildWidgettheStatefulWidget, it is withNestedcompatibleStatefulWidget

The Provider component

Provider components fall into four categories as follows:

Nested series

MultiProvider: Improves code readability and reduces code duplication by combining multiple providers into a single linear component provider.

SingleChildStatefulWidget series

  • Selector0: This is the base class for Selector to Selector6
  • Selector1-6:They are theSelector0withProvider.ofCombined use of grammar sugar, inherited fromSelector0

SingleChildStatelessWidget series

  • Consumer1-6:The consumer, it’s just calledProvider.of, the main function is to fetch from the top levelProvider<T>And passed its value tobuilder.
  • InheritedProvider: InheritedWidget, and all inheritors of the class can passProvider.ofIn order to getvalue
  • DeferredInheritedProvider: InheritedProviderClass to listen on a stream or receive oneFuture
  • StreamProvider: Listens for streams and exposes the current and latest values.
  • FutureProvider:To receive aFutureAnd in its entrycompleteState updates components that depend on it.
  • ListenableProvider:Special for use by the listenerprovider.ListenableProviderListens on the object and updates dependencies on the object when the listener is calledwidgets.
  • ChangeNotifierProvider:ChangeNotifierTo provide theListenableProviderSpecification, which is automatically called when neededChangeNotifier.dispose.
  • ListenableProxyProvider0: visible proxy provider, mainly from other providers to obtain values.
  • ListenableProxyProvider1-6:It is aListenableProviderA variant of inheritanceListenableProxyProvider0Get values from other providers
  • ChangeNotifierProxyProvider0:Mainly used for building and synchronizationChangeNotifiertheChangeNotifierProvider.
  • Provider: The most basic component of a Provider that accepts an arbitrary value and exposes it.
  • ProxyProvider0:The values it exposes are built by creating or updating and then passed toInheritedProvider.
  • ProxyProvider1-6: ProxyProvider0Grammar sugar.

InheritedContext series

  • InheritedContext:InheritedProviderThe associatedBuildContextTo provide a public value
  • ReadContext: Exposes the read method
  • SelectContext: Add a selection method to BuildContext.
  • WatchContext: Exposes the watch method.

Basic Use of Provider

Step 1: Add dependencies

All of the code in this article is basically null-safe, and all dart SDK versions are >=2.12.0 <3.0.0, with the latest official release being ^6.0.1

environment:
  sdk: "> = 2.12.0 < 3.0.0"

dependencies:
  flutter:
    sdk: flutter

  provider: ^6.01.
Copy the code

Step 2: Define the data you want to share

Here we create a class called CountNotifier that inherits from ChangeNotifier. In our case, we use the counter as a case, so we define a variable called count and a increment method to change the value. Increment is used to change count by +1, and notifyListeners() are called to update the data.

import 'package:flutter/material.dart';

class CountNotifier with ChangeNotifier {

  int count = 0;

  voidincrement() { count++; notifyListeners(); }}Copy the code

Step 3: Initialize at the application portal

We initialized the shared data defined before the MaterialApp as follows:

import 'package:flutter/material.dart';
import 'package:flutter_provider_example/provider_count_example/count_notifier.dart';
import 'package:flutter_provider_example/provider_count_example/provider_count_example.dart';
import 'package:provider/provider.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return ChangeNotifierProvider(
      create: (_) => CountNotifier(),
      child: MaterialApp(
        debugShowCheckedModeBanner: false, home: ProviderCountExample(), ), ); }}Copy the code

Step 4: Use shared data

Increment (); unter.count.tostring (); unter.count.tostring ()

import 'package:flutter/material.dart';
import 'package:flutter_provider_example/provider_count_example/count_notifier.dart';
import 'package:provider/provider.dart';

class ProviderCountExample extends StatefulWidget {
  @override
  _ProviderCountExampleState createState() => _ProviderCountExampleState();
}

class _ProviderCountExampleState extends State<ProviderCountExample> {

  @override
  Widget build(BuildContext context) {

    final counter = Provider.of<CountNotifier>(context);

    return Scaffold(
      appBar: AppBar(
        title: Text("InheritedWidget"),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: (){
          counter.increment();
        },
        child: Icon(Icons.add),
      ),
      body: Center(
        child: Text(counter.count.toString(),
          style: TextStyle(
              color: Colors.red,
              fontSize: 50),),),); }}Copy the code

conclusion

With an introduction, advantages, class structure and explanation, and a basic usage example, providers are obviously easier to use than using inheritedWidgets. But it’s a little more complicated in terms of its provider and consumer classes, which we’ll cover in a later section