微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

带动画的CustomPaint:避免重新创建对象

如何解决带动画的CustomPaint:避免重新创建对象

假设我有一个对象

class logoDrawer extends CustomPainter {

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

   void Paint(Canvas canvas,Size size)
   {
      _paintStuff();
   }
}

x的值通过动画从外部改变,而_initStuff方法可能很昂贵,但并不取决于x的值。

如果我接下来要使用_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;
    }
}

从技术上讲这是可行的,但控制台仍在继续打印

创建了新的logoDrawer对象

经常(不是每次重绘时)。这意味着初始化也经常重做,这对资源造成了很大的损失。实际上,我实际上只想创建一次对象,通过动画更改x的值,只发出重绘,而不创建新对象。我想到的是一次创建自定义画笔并更新其内部值,但这似乎不会触发重新绘制

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

    void _onClick() {
        _controller = AnimationController(
        duration: Duration(milliseconds: animDuration),reverseCurve: Curves.eaSEOut))
        ..addListener(() {
            setState(() {
                x = x+1;
                // OR 
                painter.x = x+1;
            });
        });
        _controller.forward().orCancel;
    }
}

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

解决方法

仅当某些变量已发生更改,例如本示例中的Flutter analog Clock

时,才可能使用 shouldRepaint 方法触发重绘。 ,

您可以做的是创建一个包含所有初始化数据的类,并将其初始化为状态并将其传递给painter。这样,您每次都会有一个新的painter实例,但是不需要初始化它,因为该数据会传入。

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

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。