这里是坚果前端小课堂,大家喜欢的话,可以关注我的公众号“坚果前端,”,或者加我好友,获取更多精彩内容

嵌套列表 - ShrinkWrap 与 Slivers

使用 ShrinkWrap 的列表列表

下面是一些使用​​ListView​​对象呈现列表列表的代码,内部列表的​​shrinkWrap​​值设置为 true。​​shrinkWrap​​强行评估整个内部列表,允许它请求有限的高度,而不是通常的​​ListView​​对象高度,即无穷大!

下面是基本的代码结构:

</>复制代码

  1. ListView(
    // Setting `shrinkWrap` to `true` here is both unnecessary and expensive.
    children: [
    ListView.builder(
    itemCount: list1Children.length,
    itemBuilder: (BuildContext context, int index) {
    return list1Children[index];
    },
    // This forces the `ListView` to build all of its children up front,
    // negating much of the benefit of using `ListView.builder`.
    shrinkWrap: true,
    ),
    ListView.builder(
    itemCount: list2Children.length,
    itemBuilder: (BuildContext context, int index) {
    return list2Children[index];
    },
    // This forces the `ListView` to build all of its children up front,
    // negating much of the benefit of using `ListView.builder`.
    shrinkWrap: true,
    ),
    ...
    ],
    )

注意:观察外部​​ListView​​没有将其​​shrinkWrap​​ 值设置为​​true​​。只有内部列表需要设置​​shrinkWrap​​。

另请注意:虽然​​ListView.builder​​(默认情况下)有效地构建其子项,为您节省构建屏幕外小部件的不必要成本,但设置 ​​shrinkWrap​​为​​true​​覆盖此默认行为!

</>复制代码

  1. import package:flutter/material.dart;
    import dart:math as math;

    void main() {
    runApp(ShrinkWrApp());
    }

    class ShrinkWrApp extends StatelessWidget {
    @override
    Widget build(BuildContext context) {
    return MaterialApp(
    debugShowCheckedModeBanner: false,
    title: ShrinkWrap vs Slivers,
    home: Scaffold(
    appBar: AppBar(
    title: const Text("ShrinkWrap, Street Rat, I dont, Buy that!"),
    ),
    body: const ShrinkWrapSlivers(),
    ),
    );
    }
    }

    class ShrinkWrapSlivers extends StatefulWidget {
    const ShrinkWrapSlivers({
    Key? key,
    }) : super(key: key);

    @override
    _ShrinkWrapSliversState createState() => _ShrinkWrapSliversState();
    }

    class _ShrinkWrapSliversState extends State {
    List innerLists = [];
    final numLists = 15;
    final numberOfItemsPerList = 100;

    @override
    void initState() {
    super.initState();
    for (int i = 0; i < numLists; i++) {
    final _innerList = [];
    for (int j = 0; j < numberOfItemsPerList; j++) {
    _innerList.add(const ColorRow());
    }
    innerLists.add(
    ListView.builder(
    itemCount: numberOfItemsPerList,
    itemBuilder: (BuildContext context, int index) => _innerList[index],
    shrinkWrap: true,
    physics: const NeverScrollableScrollPhysics(),
    ),
    );
    }
    }

    @override
    Widget build(BuildContext context) {
    return ListView.builder(
    itemCount: numLists,
    itemBuilder: (context, index) => innerLists[index]);
    }
    }

    @immutable
    class ColorRow extends StatefulWidget {
    const ColorRow({Key? key}) : super(key: key);

    @override
    State createState() => ColorRowState();
    }

    class ColorRowState extends State {
    Color? color;

    @override
    void initState() {
    super.initState();
    color = randomColor();
    }

    @override
    Widget build(BuildContext context) {
    print(Building ColorRowState);
    return Container(
    decoration: BoxDecoration(
    gradient: LinearGradient(
    begin: Alignment.topLeft,
    end: Alignment.bottomRight,
    colors: [
    randomColor(),
    randomColor(),
    ],
    ),
    ),
    child: Row(
    children: [
    Padding(
    padding: const EdgeInsets.all(8.0),
    child: Container(height: 50, width: 50, color: Colors.white),
    ),
    Flexible(
    child: Column(
    children: const [
    Padding(
    padding: EdgeInsets.all(8),
    child: Text(这里是 坚果前端小课堂!,
    style: TextStyle(color: Colors.white)),
    ),
    ],
    ),
    ),
    ],
    ),
    );
    }
    }

    Color randomColor() =>
    Color((math.Random().nextDouble() * 0xFFFFFF).toInt()).withOpacity(1.0);

一切都建立起来!

当您滚动浏览此 UI 并注意该​​ColorBarState.build​​方法的调用方式时,会出现可怕的部分 。每个内部列表包含 100 个元素,因此当 UI 加载时,您会立即看到 100 个“Building ColorBarState”的实例打印到控制台,

更糟糕的是,一旦向下滚动大约一百行,就会再生成一百行。????????????

flutter

而且你滑动的快的时候列表会抖动!

重新构建嵌套列表

要了解如何使您的用户免受卡顿威胁,请等待我的第二节,下一节将使用 Slivers 而不是 ListViews 重建相同的 UI。