【问题标题】:Widgets present outside the Consumer are also getting rebuilt while using ChangeNotifierProvider in Flutter在 Flutter 中使用 ChangeNotifierProvider 时,消费者之外的小部件也会被重建
【发布时间】:2021-06-24 03:31:16
【问题描述】:

所以我只是在玩提供程序小部件。下面是我的 Entry 主函数。

void main() async {

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

}

如上面的代码所示,我在 MaterialApp 上方添加了提供程序小部件,以便它可以在整个应用程序中使用。

下面是我的 GameScene 小部件:

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,
              );
            }
          )
        ],
      ),
    );
  }

}

从上面的代码中可以看出,我已经用 Consumer 包裹在 Image 小部件上,因为它是唯一的小部件,每次提供者一个新值时都会移动到一个新的位置,并休息所有其他小部件(草精灵图像和堆栈上方的蓝色容器)将保持不变,无论提供者的更新如何。

为了检查它是否按照我上面所说的方式工作,我用 Builder 包装了草精灵图像小部件(如上面的代码所示),以检查它是否正在重建,即使它在 Consumer 小部件之外,遗憾的是它每次更新都会重建。

到目前为止,我认为只有 Consumer 的 builder 函数内部的小部件会被重建,而新值由提供者提供,但这里 Consumer 之外的小部件也在重建。

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

提前感谢您的帮助。

【问题讨论】:

    标签: flutter flutter-provider


    【解决方案1】:
     _provider = Provider.of<GameProvider>(context);    
    

    把这个改成这个:

     _provider = Provider.of<GameProvider>(context,listen: false );    
    

    【讨论】:

    • 感谢您的解决方案 :)。之前不知道listen参数。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-09-09
    • 2021-09-18
    • 2020-05-10
    • 2019-11-24
    • 2020-08-09
    相关资源
    最近更新 更多