0

当我使用依赖于该类的所有小部件更新ChangeNotifier类实例变量时,将重新构建(好像我使用的是 a而不是小部件)。如果我使用小部件和相关参数正确更新实例变量,则仅根据更改的数据更新小部件Provider.of<T>(context, listen: true).valueSelectorConsumerSelectorProvider.of<T>(context, listen: false).valueSelectorselector:

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

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

class ModState with ChangeNotifier {
  int _counter0 = 0;
  int get counter0 => _counter0;
  set counter0(int _value) {
    _counter0 = _value;
    notifyListeners();
  }

  int _counter1 = 0;
  int get counter1 => _counter1;
  set counter1(int _value) {
    _counter1 = _value;
    notifyListeners();
  }

    int get counter012 => (_counter0 + _counter1);

  static ModState of(BuildContext context, {bool listen = true}) =>
      Provider.of<ModState>(context, listen: listen);
}

class AppMain extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MultiProvider(
        providers: [ChangeNotifierProvider(builder: (_) => ModState())],
        child: MaterialApp(home: Scaffold(
            // Wrap in Builder Widget to clarify context
            body: Builder(builder: (context) {
          return SafeArea(
              child: Column(children: <Widget>[
            Row(
              children: <Widget>[
                Tooltip(
                  message: 'Update counter 0, rebuild counter 0 Text widget',
                  child: RaisedButton(
                    onPressed: () {
                      // Counterintuitively, user Provider.of<mode>(context, listen: false) to avoid rebuilding all children
                      ModState.of(context, listen: false).counter0++;
                      debugPrint(
                          'Counter0: button pressed ${ModState.of(context, listen: false).counter0}');
                    },
                    child: Text('Update 0, rebuild 0'),
                  ),
                ),
                Selector<ModState, int>(
                  selector: (_, _state) => _state.counter0,
                  builder: (_, _data, __) {
                    debugPrint(
                        'Counter0, builder invoked ${ModState.of(context, listen: false).counter0}');
                    return Text(
                        '$_data / ${ModState.of(context, listen: false).counter012}');
                  },
                )
              ],
            ),
            Row(
              children: <Widget>[
                Tooltip(
                  message: 'Update counter 1, rebuild counter 1 Text widget',
                  child: RaisedButton(
                    onPressed: () {
                      // Counterintuitively, user Provider.of<mode>(context, listen: false) to avoid rebuilding all children
                      ModState.of(context, listen: false).counter1++;
                      debugPrint(
                          'Counter1: button pressed ${ModState.of(context, listen: false).counter1}');
                    },
                    child: Text('Update 1, rebuild 1'),
                  ),
                ),
                Selector<ModState, int>(
                  selector: (_, _state) => _state.counter1,
                  builder: (_, _data, __) {
                    debugPrint(
                        'Counter1, builder invoked ${ModState.of(context, listen: false).counter1}');
                    return Text(
                        '$_data / ${ModState.of(context, listen: false).counter012}');
                  },
                )
              ],
            ),
          ]));
        }))));
  }
}

虽然我现在的代码有效,但listen: false就我对该参数的理解而言,使用该参数是违反直觉的。我想了解原因,以便总体上改进我的代码

4

1 回答 1

0

从这篇文章中提到的内容来看,Selector正在按预期工作。如文档中所述,小部件将在selector(BuildContext, A). 这里似乎发生的是整个Widget build()被重建。再说一次,如果 Widgets 上显示的数据是正确的并且没有性能问题,那么它是可以通过的。但是,如果您想阻止重建,您可能需要重新考虑 Provider 在页面上的布局方式。

于 2022-02-01T03:39:44.610 回答