Flutter ListView.Builder 导致滚动不连贯。如何使滚动平滑?

Posted

技术标签:

【中文标题】Flutter ListView.Builder 导致滚动不连贯。如何使滚动平滑?【英文标题】:Flutter ListView.Builder results in choppy scrolling. How do I make the scrolling smooth? 【发布时间】:2020-04-14 12:38:35 【问题描述】:

我正在尝试构建一个应用,其中包含可加载的预订列表。当用户滚动浏览这些预订时,滚动非常不稳定。我已经完成了所有调试、配置文件和发布模式的测试,但滚动不连贯的问题仍然存在。 iosandroid 都是如此。这是我已经尝试过的 -

    我已经尝试过使用 const AlwaysScrollableScrollPhysics(), 我试过使用不带动画和带动画。在这两种情况下都存在不连贯的滚动 我已经尝试过 cached.network.image。出现不稳定的滚动。

即使在配置文件模式下,ListView 构建器也需要超过 16 毫秒来构建 ListTile

return ListView.builder(
      physics: const AlwaysScrollableScrollPhysics(),
      itemCount: widget.bookings.length,
      scrollDirection: Axis.vertical,
      itemBuilder: (context, int index) 
        var count = 10;
        var animation = Tween(begin: 0.0, end: 1.0).animate(CurvedAnimation(
            parent: animationController,
            curve: Interval((1 / count) * index, 1.0,
                curve: Curves.fastOutSlowIn)));
        animationController.forward();

        return BookingListCard(
          booking: widget.bookings[index],
          bookings: widget.bookings,
          animation: animation,
          animationController: animationController,
        );
      ,
    );
AnimatedBuilder(
      animation: animationController,
      builder: (BuildContext context, Widget child) 
        return FadeTransition(
          opacity: animation,
          child: new Transform(
            transform: new Matrix4.translationValues(
                0.0, 50 * (1.0 - animation.value), 0.0),
            child: Padding(
              padding:
                  const EdgeInsets.only(left: 0, right: 0, top: 0, bottom: 0),
              child: InkWell(
                splashColor: Colors.transparent,
                onTap: () 
                  callback();
                ,
                child: Padding(
                  padding: const EdgeInsets.only(top: 8.0),
                  child: Card(
                    color: AppTheme.halfWhite,
                    elevation: 0,
                    child: ListTile(
                      onTap: () 
                        Navigator.of(context)
                            .push(_createRoute(booking, booking.id));
                      ,
                      leading: Container(
                        width: _size,
                        height: _size,
                        decoration: BoxDecoration(
                          shape: BoxShape.circle,
                          image: DecorationImage(
                            image: NetworkImage(booking.guest.imageUrl),
                            fit: BoxFit.fill,
                          ),
                        ),
                      ),
                      title: Padding(
                        padding: const EdgeInsets.only(top: 10.0),
                        child: Text(
                          booking.guest.firstName,
                          style: AppTheme.title,
                        ),
                      ),
                      subtitle: Column(
                        crossAxisAlignment: CrossAxisAlignment.start,
                        children: <Widget>[
                          Row(
                            children: <Widget>[
                              Text(
                                '$(DateFormat("E, d MMM").format(DateTime.parse(booking.checkIn))).toUpperCase()  ',
                                style: AppTheme.caption,
                              ),
                              Image.asset(
                                "assets/images/arrow.png",
                                width: 12,
                                height: 12,
                              ),
                              Text(
                                '  $(DateFormat("E, d MMM").format(DateTime.parse(booking.checkOut))).toUpperCase()',
                                style: AppTheme.caption,
                              )
                            ],
                          ),
                          Padding(
                            padding:
                                const EdgeInsets.only(top: 8.0, bottom: 8.0),
                            child: DashedDivider(
                                color: Colors.black.withOpacity(0.6),
                                dashWidth: 0.1),
                          ),
                          Text(
                            '$(booking.status).toUpperCase()',
                            style: TextStyle(
                              color: statusColorFinder(booking.status),
                              fontFamily: AppTheme.fontName,
                              fontWeight: FontWeight.bold,
                              fontSize: 12,
                              letterSpacing: 0.4,
                              height: 0.9,
                            ),
                          ),
                        ],
                      ),
                      // trailing: Icon(Icons.more_vert),
                      trailing: booking.status == 'Pending' ? MyBullet() : null,
                      isThreeLine: false,
                    ),
                  ),
                ),
              ),
            ),
          ),
        );
      ,
    );

【问题讨论】:

试过官方文档中最简单的ListView.builder例子?它也会变得波涛汹涌吗? 官方文档中的例子还是有点混乱 所以您只有一个ListView,仅此而已?没有异步任务,没有隔离等? 为什么你一次又一次地宣布动画?只需在您的状态类中声明一次并重用变量,而不是一次又一次地定义。 【参考方案1】:

在配置文件模式下运行能够追踪我生成虚线的问题 使用列表生成器而不是使用 contianer,这是导致滞后的原因 替换了以下代码

 DashedDivider(color: Colors.black.withOpacity(0.6),
dashWidth: 0.1)

这个

Container(color: Colors.black45,
height: 1,
width: double.maxFinite,
)

【讨论】:

所以我在问你官方文档中最简单的ListView.builder例子,你为什么说它也很不稳定? 在官方示例中,在某些地方,滚动过程需要超过 50 毫秒,导致断断续续 所以如果最简单的例子是不稳定的,那么你更复杂的代码也会是不稳定的,你不觉得吗?我的意思是你的开发环境一定有问题 是的,对于复杂的,我能够达到 20 毫秒以下,这很好,但不是正确的解决方案。对于我尝试使用两台不同电脑的开发环境,它仍然相同 这听起来像是在 v1.12.13 中修复的。现在对你好点了吗? github.com/flutter/flutter/issues/22314

以上是关于Flutter ListView.Builder 导致滚动不连贯。如何使滚动平滑?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Flutter 中添加 ListView.builder 的填充顶部?

Flutter - ListView.builder:初始滚动位置

Flutter:ListView.builder 创建列

Flutter - 另一个 Listview 中的 Listview.builder

Flutter:ListView.builder 中的自动垂直高度

Flutter 应用程序,ListView.builder 首次运行时出现错误。需要重启应用(ListView.builder 和 image_picker)