0

我使用模型的 ChangeNotifierProvider,它有一个“数字”属性和一个为其设置随机值的方法。有2条路线。在第一个中,有一个变量使用context.selector context.watch(无关紧要)侦听此属性,然后在 aText小部件。还有一个按钮调用模型的方法,设置随机值。最初,如果没有更改屏幕,则按下此按钮时,将按预期重建小部件。推送到另一条路线然后返回第一条路线时会出现问题。如果再次按下按钮,则小部件会重建两次,因为提供者由于某种原因也被更改了两次。而且,您在屏幕之间切换的次数越多,当您按下用于设置随机值的按钮时,小部件重建的次数就越多。您可以在下面看到来自 Dart DevTools 的带有日志的屏幕截图。这里我举了一个小例子,只是为了说明我的问题,但是在另一个项目中,不是一个简单的文本小部件,而是一个带有数据的表格,每次换屏后性能下降变得更加明显,

class MyModel extends ChangeNotifier {
  int _number = 0;
  int get number => _number;

  void setRandomNumber() {
    print('Set random number');
    _number = Random().nextInt(1000);
    notifyListeners();
  }
}
class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return ChangeNotifierProvider<MyModel>(
      create: (context) => MyModel(),
      child: MaterialApp(
        routes: {
          '/home': (context) => MyHomePage(),
          '/second': (context) => SecondPage(),
        },
        initialRoute: '/home',
      ),
    );
  }
}
class MyHomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final number = context.select<MyModel, num>((model) => model.number);
    print('REBUILD');

    return Scaffold(
      body: SafeArea(
        child: Column(
          children: [
            Text(number.toString()),
            TextButton(
              child: Text('Go to Page 2'),
              onPressed: () {
                print('Go to Page 2');
                Navigator.pushNamed(context, '/second');
              },
            ),
            TextButton(
              child: Text('Set Random Number'),
              onPressed: () => context.read<MyModel>().setRandomNumber(),
            ),
          ],
        ),
      ),
    );
  }
}
class SecondPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Center(
      child: TextButton(
        child: Text('Go to Home Page'),
        onPressed: () {
          print('Go to Home Page');
          Navigator.pushNamed(context, '/home');
        },
      ),
    );
  }
}

安慰:

flutter: Set random number
flutter: REBUILT

flutter: Go to Page 2
flutter: Go to Home Page

flutter: Set random number
flutter: REBUILT
flutter: REBUILT

DevTools 中的日志

在此处输入图像描述

4

1 回答 1

0

这是因为你推而不弹出。您有一堆屏幕 1、屏幕 2、屏幕 1。您按下屏幕 1 上的按钮,它会执行设置随机数函数并通知屏幕 1 的两个实例上的侦听器。

任何时候都不要在导航堆栈中出现重复的屏幕,这通常是一个好习惯。像 auto_route 这样的包会在某种程度上强制执行此操作,尽管您也可以在不使用包的情况下进行管理。当弹出可能导致您进入同一个屏幕时,请勤奋并小心推动。

于 2021-08-13T19:40:07.867 回答