简单的 Flutter 列表视图断断续续的滚动

Ton*_*ony 9 performance flutter

我一直在评估 Flutter 在应用程序中的使用情况,并从一个非常简单的文本列表示例开始。构建第一个视图后,我注意到列表视图滚动不顺畅,因此我仔细查看了展示应用程序,结果发现,虽然Reflectly是一个漂亮的应用程序,但它也遇到了同样的问题 - 滚动非常不稳定简单的文本列表。到目前为止,我已经在 iOS 模拟器、iPhone XR、Samsung Galaxy Android 设备和 Android Pixel 2 XL 模拟器上确认了这一点。

我没有看到有关此问题的讨论,所以我想知道我是否做错了什么,但也怀疑我的示例有多简单,而且 Reflectly 也有同样的问题。

我希望社区能够理解: 1. 我是否做了任何明显错误/愚蠢的事情导致了这种情况 2. 如果你在你的设备上运行,你能看到我所看到的吗?3. 这是否已知并且将会得到解决?如果我选择使用 Flutter,我是否可以放心地看到我的列表在不久的将来会顺利滚动?

下面是您可以运行来重现此内容的代码(抱歉,这有点做作,但我想尝试一下各种 Flutter/Dart 功能):

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
        title: 'My List',
        home: Scaffold(
          appBar: AppBar(
            title: Text('My List'),
            backgroundColor: Color.fromRGBO(255, 0, 0, 0.9),
          ),
          body: Padding(
            padding: EdgeInsets.all(16.0),
            child: Column(
            children: [
              Expanded(child: TimeSelector()),
            ],
          )),
        ));
  }
}

abstract class ListItem {}

class TimeHeader implements ListItem {
  final String header;

  TimeHeader(this.header);
}

class TimeOption implements ListItem {
  final String timeString;
  final String meridian;

  TimeOption(this.timeString, this.meridian);
}

final List<ListItem> litems = [
  TimeHeader("Morning"),
  TimeOption("10:00", "am"),
  TimeOption("10:30", "am"),
  TimeOption("11:30", "am"),
  TimeHeader("Afternoon"),
  TimeOption("1:00", "pm"),
  TimeOption("1:30", "pm"),
  TimeOption("2:30", "pm"),
  TimeHeader("Night"),
  TimeOption("5:30", "pm"),
  TimeOption("6:30", "pm"),
  TimeOption("7:30", "pm"),
  TimeOption("8:30", "pm"),
  TimeOption("9:30", "pm"),
  TimeOption("10:30", "pm"),
  TimeOption("11:30", "pm"),
  TimeOption("11:45", "pm"),
  TimeOption("11:49", "pm"),
];

class TimeSelector extends StatelessWidget {
  final _headerFont = new TextStyle(fontWeight: FontWeight.w600, fontSize: 13.0, color: Color.fromRGBO(164, 164, 164, 1));
  final _smallerFont = const TextStyle(fontSize: 12.0);

  @override
  ListView build(BuildContext context) {
    return new ListView.builder(
      padding: const EdgeInsets.all(16.0),
      itemCount: litems.length,
      itemBuilder: (BuildContext ctxt, int index) => _buildItem(ctxt, index),
    );
  }

  Widget _buildItem(BuildContext ctxt, int index) {
    final item = litems[index];

    if (item is TimeHeader) {
      return new ListTile(
        title: Text(
          item.header,
          style: _headerFont,
        ),
      );
    } else if (item is TimeOption) {
      return new ListTile(
        title: Text(
          item.timeString + item.meridian.toUpperCase(),
          style: _smallerFont,
        ),
      );
    } else {
      return new Text("UNKNOWN");
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

Nim*_*yal 9

Flutter ListView 在调试模式下滚动肯定存在问题。尽管您的代码将在发布模式下正常运行,并且滚动不会出现任何滞后。但是,如果您想在调试模式下滚动而没有任何延迟,您可以更喜欢SingleChildScrollView而不是 ListView。只需将滚动小部件放入 Column 中,然后将该 Column 作为 SingleChildScrollView 的子项即可。在您的情况下,您正在使用ListView.builder。我建议您应该使用此代码来实现非常平滑的滚动:

@override
  Widget build(BuildContext context) {
    return SingleChildScrollView(
      child: Column(
        mainAxisSize: MainAxisSize.min,
        children: <Widget>[
          Flexible(
            child: ListView.builder(
              shrinkWrap: true,
              physics: NeverScrollableScrollPhysics(),
              padding: const EdgeInsets.all(16.0),
              itemCount: litems.length,
              itemBuilder: (BuildContext ctxt, int index) => _buildItem(ctxt, index),
            ),
          )
        ],
      ),
    );
  }
Run Code Online (Sandbox Code Playgroud)

不要忘记用作mainAxisSize: MainAxisSize.min列大小shrinkWrap: truephysics: NeverScrollableScrollPhysics()

物理:NeverScrollableScrollPhysics()将禁用 ListView.builder 的滚动,并且您将体验到列表的极其平滑的滚动

  • 虽然这个解决方案效果很好,但是这个解决方案的缺点在性能上表现出来,因为整个列表渲染一次。所以我们可以在应用程序中清楚地看到延迟。简单的话会增加加载时间 (3认同)

Sam*_*mer 2

如果您正在处理列表项数量非常少的静态数据,您可以使用以下命令加快列表速度addAutomaticKeepAlives: true