在Flutter中使用ChangeNotifierProvider时,消费者外部的小部件也得到了重建

在Flutter中使用ChangeNotifierProvider时,消费者外部的小部件也得到了重建,flutter,flutter-provider,Flutter,Flutter Provider,所以我只是在玩提供者小部件。下面是我的输入主要功能 void main() async { runApp( ChangeNotifierProvider<GameProvider>( create: (_) => GameProvider(), builder: (context,child) => MaterialApp(home: GameScene()), ) ); } void main()

所以我只是在玩提供者小部件。下面是我的输入主要功能

void main() async {

  runApp(
      ChangeNotifierProvider<GameProvider>(
        create: (_) => GameProvider(),
          builder: (context,child) => MaterialApp(home: GameScene()),
      )
  );

}
void main()异步{
runApp(
变更通知提供者(
创建:()=>GameProvider(),
生成器:(context,child)=>MaterialApp(home:GameScene()),
)
);
}
正如上面的代码所示,我在MaterialApp上面添加了provider小部件,这样就可以在整个应用程序中使用它

下面是我的游戏场景小部件:

import 'dart:math';

import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:river_crossing_game/Providers/GameProvider.dart';

class GameScene extends StatefulWidget {
  @override
  _GameSceneState createState() => _GameSceneState();
}

class _GameSceneState extends State<GameScene> with SingleTickerProviderStateMixin{

  double height, width;

  bool pseudoInitState = true;

  AnimationController _animationController;
  Animation _animation;


  GameProvider _provider;
  

  @override
  Widget build(BuildContext context) {

    height = MediaQuery.of(context).size.height;
    width = MediaQuery.of(context).size.width;

    if(pseudoInitState){

      _provider = Provider.of<GameProvider>(context);              /// Added this just to use the methods present inside the provider class

      _animationController = AnimationController(vsync: this,duration: Duration(seconds: 5));
      _animation = Tween<double>(begin: 0,end: 60 * 5.0).animate(_animationController);

      _provider.initPlankPos(Offset(0,height * 0.4));     /// Ignore this method

      _animation.addListener(() {
        _provider.translatePlank(_animation.value, Offset(1,0));    /// This one is just updating the position of the widget inside the Consumer
      });

      _animationController.forward();

      pseudoInitState = false;
    }


    return Material(
      child: Stack(
        children: [
          Container(height: height, width: width, color: Colors.lightBlue,),
          Align(
            alignment: Alignment.bottomCenter,
            child: Builder(builder: (context) {print("Background Build ${Random.secure().nextDouble().toString()}");return Image.asset('assets/grass_sprite.png',height: 90,width: width,fit: BoxFit.cover);}),
          ),
          Consumer<GameProvider>(
            child: Image.asset('assets/wood_plank.png',height: width * 0.15,width: width * 0.25,fit: BoxFit.cover,),
                builder: (context,value, child) {
              return Transform.translate(
                  offset: Offset(value.plankPosX,value.plankPosY),
                  child: child,
              );
            }
          )
        ],
      ),
    );
  }

}
import'dart:math';
进口“包装:颤振/材料.省道”;
导入“包:provider/provider.dart”;
导入“package:river_crossing_game/Providers/GameProvider.dart”;
类GameSecene扩展StatefulWidget{
@凌驾
_GameScenstate createState()=>\u GameScenstate();
}
类_gamescenstate使用SingleTickerProviderStateMixin扩展状态{
双高、双宽;
bool pseudoInitState=true;
AnimationController _AnimationController;
动画(动画),;
游戏提供商(GameProvider);;
@凌驾
小部件构建(构建上下文){
height=MediaQuery.of(context).size.height;
宽度=MediaQuery.of(context).size.width;
if(伪初始状态){
_provider=provider.of(context);///添加此选项只是为了使用provider类中的方法
_animationController=animationController(vsync:this,duration:duration(秒:5));
_动画=Tween(开始:0,结束:60*5.0);
_provider.initPlankPos(偏移量(0,高度*0.4));///忽略此方法
_animation.addListener(){
_provider.translatePlank(_animation.value,Offset(1,0));///这只是更新小部件在使用者中的位置
});
_animationController.forward();
伪初始状态=假;
}
退货(
子:堆栈(
儿童:[
容器(高度:高度,宽度:宽度,颜色:颜色。浅蓝色,),
对齐(
对齐:对齐.bottomCenter,
child:Builder(Builder:(context){print(“后台构建${Random.secure().nextDouble().toString()));return Image.asset('assets/grass_sprite.png',高度:90,宽度:宽度,适合:BoxFit.cover);}),
),
消费者(
子项:Image.asset('assets/wood_plank.png',高度:width*0.15,宽度:width*0.25,适合度:BoxFit.cover,),
生成器:(上下文、值、子级){
返回Transform.translate(
偏移量:偏移量(value.plankPosX,value.plankPosY),
孩子:孩子,
);
}
)
],
),
);
}
}
从上面的代码中可以看出,我已经用Consumer包装了Image widget,因为它是唯一一个将被移动到新位置的widget,每次提供者提供一个新值并休息时,所有其他widget(草精灵图像和堆栈上方的蓝色容器)都将保持不变,而不管提供者的更新如何

为了检查它是否按照我上面所说的方式工作,我用一个生成器包装了grass sprite图像小部件(如上面的代码所示),以检查它是否正在重建,即使它在消费者小部件之外,不幸的是,它在每次更新时都在重建

到目前为止,我认为只有Consumer的builder函数中的widget会得到重建,而提供者会提供新的值,但在这里,Consumer之外的widget也会得到重建

我是否没有正确使用提供者,或者我是否获得了有关提供者工作的错误信息

提前感谢您的帮助。

\u provider=provider.of(上下文);
 _provider = Provider.of<GameProvider>(context);    
将此更改为:

 _provider = Provider.of<GameProvider>(context,listen: false );    
\u provider=provider.of(上下文,侦听:false);
感谢您提供的解决方案:)。以前不知道listen参数。