【问题标题】:I have laggy animation because of setState() in my code由于我的代码中的 setState(),我的动画滞后
【发布时间】:2019-08-22 07:58:14
【问题描述】:

我有相互连接的动画网页浏览和列表浏览。但是我有一个由 setState 引起的动画问题(我已经测试了删除 setState 并且动画效果很好)。

import 'package:flutter/material.dart';

 const double _listheight = 80;

class LoyaltyPage extends StatefulWidget {
  @override
  _LoyaltyPageState createState() => new _LoyaltyPageState();
}

class _LoyaltyPageState extends State<LoyaltyPage> {
  PageController controller;
  ScrollController listcontroller;
  int selected = 0;
  List<String> images=[
    'https://images.pexels.com/photos/67636/rose-blue-flower-rose-blooms-67636.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500',
    'https://images.pexels.com/photos/67636/rose-blue-flower-rose-blooms-67636.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500',
    'https://images.pexels.com/photos/67636/rose-blue-flower-rose-blooms-67636.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500',
    'https://images.pexels.com/photos/67636/rose-blue-flower-rose-blooms-67636.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500',
  ];
  @override
  initState() {
    super.initState();
    controller = new PageController(
      initialPage: selected,
      keepPage: false,
      viewportFraction: 0.7,
    );
    listcontroller = new ScrollController();
  }

  @override
  dispose() {
    controller.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        backgroundColor: Colors.white,
        iconTheme: IconThemeData(color: Colors.black),
        title: Text(
          'Loyalty',
          style: TextStyle(color: Colors.black),
        ),
      ),
      body: Column(
        children: <Widget>[
          Expanded(
            flex: 3,
            child: new Container(
              child: new PageView.builder(
                  onPageChanged: (value) {
                  //ADDING THIS SET STATE CAUSE SELECTED COLOR WORKS BUT LAGGY ANIMATION
                  setState(() {
                    selected=value;
                  });
                    listcontroller.animateTo(value*_listheight,duration: Duration(milliseconds: 500),curve: Curves.ease);
                  },
                  itemCount: images.length,
                  controller: controller,
                  itemBuilder: (context, index) => builder(index)),
            ),
          ),
          Expanded(
            flex: 6,
            child: new Container(
              child: new ListView.builder(
                controller: listcontroller,
                itemCount: images.length,
                itemBuilder: (context,index) => _listbuilder(index),
              ),
            ),
          ),
        ],
      ),
    );
  }

  builder(int index) {
    return new AnimatedBuilder(
      animation: controller,
      builder: (context, child) {
        double value = 1.0;
        if (controller.position.haveDimensions) {
          value = controller.page - index;
          value = (1 - (value.abs() * .4)).clamp(0.0, 1.0);
        }
        return new Center(
          child: new SizedBox(
            height: Curves.easeOut.transform(value) * 180,
            width: Curves.easeOut.transform(value) * 270,
            child: child,
          ),
        );
      },
      child: new Card(
        shape: RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(20))),
          semanticContainer: true,
          clipBehavior: Clip.antiAliasWithSaveLayer,
        child:Container(
          child: Image.network(images[index],fit: BoxFit.fill,)
        ),
      ),
    );
  }

  _listbuilder(int index){
    return Container(
      height: _listheight,
      child: Column(
        children: <Widget>[
          ListTileTheme(
            selectedColor: Colors.blueAccent,
            child: ListTile(
              title: Text(images[index],maxLines: 1,overflow: TextOverflow.ellipsis,),
              subtitle: Text('Level : Gold'),
              leading: GestureDetector(
                onTap: (){
                  //ADDING THIS SET STATE CAUSE SELECTED COLOR WORKS BUT LAGGY ANIMATION
                  setState(() {
                    selected=index;
                  });
                  controller.animateToPage(index,duration: Duration(milliseconds: 500),curve: Curves.ease); 
                },
                child: Icon(
                  Icons.credit_card),
              ),
              trailing: Icon(Icons.navigate_next),
              selected: index==selected,//THIS IS THE SELECTED THAT I TRIED TO CHANGE
            ),
          ),
          Divider(height: 1,color: Colors.black45,),
        ],
      ),
    );
  }
}

我在 pagechanged 和我的应用程序的前导 listtile 上的 2 个地方使用 setState。这是我的应用程序的样子。

第一个是我的应用程序的预期输出,但它滞后, 第二个动画流畅,但文字颜色没有变化。

【问题讨论】:

  • 您是否在配置文件/发布模式下运行该应用程序?先试试这个。调试模式有时非常滞后。
  • 哇。这是我第一次在发布模式下运行它,它运行得非常流畅。感谢@DanielSzy。但是,只是为了确保我的代码中还有其他选项可以优化它吗?因为当我没有使用 setState 时,即使在调试模式下它也能顺利运行。
  • 我会发布一个答案,因为评论不会提供足够的字符 tho

标签: flutter dart setstate flutter-animation


【解决方案1】:

尝试在发布模式或配置文件模式下运行您的应用程序。

只有 CircularProgressIndicator() 旋转时,调试模式下的动画会出现性能问题。这是因为在调试模式下,Dart 编译的是 JIT 而不是 AOT。因此,绘图引擎在动画期间绘制 UI 时需要每秒编译 60 次,才能像在 AOT 模式下一样流畅地运行。正如人们所猜测的那样,这将占用大量资源。

只要您不在AnimationController..addListener() 上调用setState({}),您的具体实现就应该没问题。有关动画的更多详细信息,请参阅本文和setState({})https://medium.com/flutter-community/flutter-laggy-animations-how-not-to-setstate-f2dd9873b8fc

【讨论】:

  • 感谢您的解释。现在通过在发布模式下运行我的应用程序解决了我的问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-04-19
  • 1970-01-01
  • 2016-09-22
  • 2021-04-25
  • 1970-01-01
相关资源
最近更新 更多