web-dev-qa-db-fra.com

Comprendre comment Listen: false fonctionne lorsqu'il est utilisé avec le fournisseur <SomeType> .of (context, listen: false)

Je travaille à comprendre comment le package Provider fonctionne avec Flutter, mais je ne comprends pas comment fonctionne listen: false.

J'ai écrit du code de base en utilisant l'exemple Counter habituel d'un nouveau projet Flutter. J'ai créé trois types de widgets sans état utilisant chacun un fournisseur:

  1. Provider.of (contexte)
  2. Consommateur
  3. Provider.of (contexte, écouter: faux)

Le troisième exemple était de montrer comment accéder à l'objet fournisseur et appeler les méthodes dessus sans qu'il soit reconstruit.

Lorsque j'exécute l'application, tous les nombres de widgets changent - et je m'attends à ce que cela change dans les deux premiers.

Ceci est un exemple simple - qu'est-ce que je fais mal?

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

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

class Counter with ChangeNotifier {
  int _count = 0;
  int get count => _count;

  void increment() {
    _count++;
    notifyListeners();
  }
}

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MultiProvider(
      providers: [
        ChangeNotifierProvider(builder: (_) => Counter()),
      ],
      child: MaterialApp(
        title: 'Provider Demo',
        theme: ThemeData(
          primarySwatch: Colors.amber,
        ),
        home: MyHomePage(title: 'Provider Demo Home Page'),
      ),
    );
  }
}

class MyHomePage extends StatelessWidget {
  MyHomePage({Key key, this.title}) : super(key: key);

  final String title;

  @override
  Widget build(BuildContext context) {
    Counter counter = Provider.of<Counter>(context);
    return Scaffold(
      appBar: AppBar(
        title: Text(title),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            ExampleProviderWidget(),
            ExampleConsumerWidget(),
            ExampleNoListenWidget()
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () => counter.increment(),
        tooltip: 'Increment',
        child: Icon(Icons.add),
      ),
    );
  }
}

class ExampleProviderWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    Counter counter = Provider.of<Counter>(context);

    return Container(
      color: Colors.green,
      child: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text(
              'Provider.of<Counter>(context):',
            ),
            Text(
              '${counter.count}',
              style: Theme.of(context).textTheme.display1,
            ),
          ],
        ),
      ),
    );
  }
}

class ExampleConsumerWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Consumer<Counter>(
      builder: (context, counter, _) {
        return Container(
          color: Colors.blue,
          child: Center(
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              children: <Widget>[
                Text(
                  'Consumer<Counter>(context):',
                ),
                Text(
                  '${counter.count}',
                  style: Theme.of(context).textTheme.display1,
                ),
              ],
            ),
          ),
        );
      },
    );
  }
}

class ExampleNoListenWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    Counter counter = Provider.of<Counter>(context, listen: false);

    return Container(
      color: Colors.red,
      child: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text(
              'Provider.of<Counter>(context, listen: false):',
            ),
            Text(
              '${counter.count}',
              style: Theme.of(context).textTheme.display1,
            ),
            RaisedButton(
              child: Text("Increment"),
              onPressed: () => counter.increment(),
            )
          ],
        ),
      ),
    );
  }
}

4
Joe Nalewabau

Ce que Remi a suggéré est une approche de travail (hack). Mais je crois que la meilleure façon dans ce cas sera de supprimer l'appel Counter counter = Provider.of (context); à partir de MyHomePageClass. Cet appel pollue la portée de votre objet Counter. Comme suggéré par flutter.io, Il est préférable de placer vos widgets Consumer aussi profondément que possible dans l'arborescence . Comme vous l'avez fait dans ExampleProviderWidget (), ExampleConsumerWidget (), ExampleNoListenWidget (). Faites donc du flottantActionButton une classe de widget distincte et ayez son propre Provider.of (contexte). Et votre MyHomePageClass n'aura pas à appeler Provider.of.

0
mykey