Flutter 使用动画自定义绘制:避免重新创建对象

Flutter 使用动画自定义绘制:避免重新创建对象,flutter,flutter-animation,Flutter,Flutter Animation,假设我有一个对象 class LogoDrawer extends CustomPainter { int x; LogoDrawer(this.x){ print('New logoDrawer object created'); _initStuff(); } void Paint(Canvas canvas, Size size) { _paintStuff(); } } 而x的值通过动画在外部发生变化,

假设我有一个对象

class LogoDrawer extends CustomPainter {

   int x;
   
   LogoDrawer(this.x){
      print('New logoDrawer object created');
      _initStuff();
   }

   void Paint(Canvas canvas, Size size)
   {
      _paintStuff();
   }
}
x
的值通过动画在外部发生变化,
\u initStuff
方法可能很昂贵,但不依赖于
x
的值

如果我用
\u onClick
方法设置动画

class _SomeState extends State<SomeWidget>  with TickerProviderStateMixin {

    x = 0;

    Widget build(BuildContext context){
        return GestureDetector(
                child: CustomPaint(
                  willChange: true,
                  painter: LogoDrawer(x)
                ),
                onTap: _onClick,
              );
    }

    void _onClick() {
        _controller = AnimationController(
        duration: Duration(milliseconds: 1000),
        vsync: this,
        );

        animation = Tween(begin: 0.4, end: 0.0).animate(CurvedAnimation(
            parent: _controller, curve: Curves.ease, reverseCurve: Curves.easeOut))
        ..addListener(() {
            setState(() {
                x = x+1;
            });
        });
        _controller.forward().orCancel;
    }
}

请注意,这是对我的问题的一般描述,我正在使用的实际代码远比这复杂。

您可以创建一个类,该类保存您初始化的所有数据,并在您的状态下初始化一次,然后将其传递给您的绘制者。这样,您每次都有一个新的painter实例,但不需要初始化它,因为数据是传入的


或者,您可以将该数据放入
static
成员中,并拥有自定义painter类的静态初始化方法。例如,在我的一个项目中,我有两个画家可以在两者之间切换,一个只是用不同的颜色填充,另一个使用纹理。由于需要加载所有纹理,因此并非每个开关都要加载,但是,在启动屏幕中只有一次。

可能只有当某个变量发生了变化时,才可以使用shouldrepain方法触发重画,如本例所示:

是的,我也在考虑这一点,但画师中有一些逻辑需要重构。我只是希望有一个通过
setState
@nvoigt发布重画的简单解决方案
CustomPainter
中已经有一个内置解决方案:
repaint
中使用的参数
CustomPainter
constructor@pskink听起来不错,为什么不从中作出回答?@pskink我似乎在构造函数中找不到这个
repaint
参数@WouterVandenputte-see——它写道:“只要
repaint
通知它的监听者,油漆工就会重新油漆。”检查
CustomPaint
构造函数的
repaint
参数,或者将
CustomPainter
changeinnotifier
交替混合使用-有关仍会触发新对象创建而不是重新绘制的更多信息,请参阅。我宁愿做一些类似于
myPainter.setDateTime(现在)
的事情,然后再做一些类似于
myPainter.repain()
的事情,但不幸的是后者没有exist@WouterVandenputte那么这是否意味着
CustomPainter
repaint
参数不起作用呢?嗯,我不太清楚。这是一个相当复杂的应用程序。有一个
状态
,它调用
onClick
,然后创建一个具有随机持续时间的动画,以使画师的特定部分旋转,而不是整个画师旋转。但是在创建我的
foopainer
之前,我必须给出这个动画。完成此动画后,旋转应仅从其所在位置继续,因此不会重置为初始旋转为零弧度的新对象新建
onClick
,然后创建新动画,但如何将新动画传递到现有的
foopainer
?我只能创建一个新实例,不能更新它
repaint
参数
class _SomeState extends State<SomeWidget>  with TickerProviderStateMixin {

    x = 0;
    var myPainter = LogoDrawer(x);

    Widget build(BuildContext context){
        return GestureDetector(
                child: CustomPaint(
                  willChange: true,
                  painter: myPainter
                ),
                onTap: _onClick,
              );
    }

    void _onClick() {
        _controller = AnimationController(
        duration: Duration(milliseconds: animDuration),
        vsync: this,
        );

        animation = Tween(begin: 0.4, end: 0.0).animate(CurvedAnimation(
            parent: _controller, curve: Curves.ease, reverseCurve: Curves.easeOut))
        ..addListener(() {
            setState(() {
                x = x+1;
                // OR 
                painter.x = x+1;
            });
        });
        _controller.forward().orCancel;
    }
}