重新构建嵌套列表
我们接着上一期的继续今天的 内容
使用 Slivers 的列表列表
下面的代码构建了与之前相同的 UI,但这次它使用Slivers
而不是收缩包装ListView
对象。本页的其余部分将引导您逐步完成更改。
如何将嵌套列表迁移到 Slivers
第1步
首先,将最外面的 ListView 更改为SliverList
.
// Before @override Widget build(BuildContext context) { return ListView.builder( itemCount: numberOfLists, itemBuilder: (context, index) => innerLists[index], ); } 复制代码
变成:
// After @override Widget build(BuildContext context) { return CustomScrollView(slivers: innerLists); } 复制代码
第2步
其次,将内部列表的类型从List<ListView>
更改为 List<SliverList>
。
// Before List<ListView> innerLists = []; 复制代码
变成:
// After List<SliverList> innerLists = []; 复制代码
第 3 步
现在是时候重建内部列表了。的SliverList
类是比原始略有不同ListView
的类,与主要差异是的外观delegate
。
原始版本ListView
对所有内容都使用对象,不知道内部构建器构造函数将被shrinkWrap
.
// Before @override void initState() { super.initState(); for (int i = 0; i < numberOfLists; i++) { final _innerList = <ColorRow>[]; 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(), ), ); } } 复制代码
更改后,ListView
对象被替换为SliverList
对象,每个对象都使用一个SliverChildBuilderDelegate
来提供高效的按需构建。
// After @override void initState() { super.initState(); for (int i = 0; i < numLists; i++) { final _innerList = <ColorRow>[]; for (int j = 0; j < numberOfItemsPerList; j++) { _innerList.add(const ColorRow()); } innerLists.add( SliverList( delegate: SliverChildBuilderDelegate( (BuildContext context, int index) => _innerList[index], childCount: numberOfItemsPerList, ), ), ); } } 复制代码
完整代码:
import 'package:flutter/material.dart'; import 'dart:math' as math; void main() { runApp(SliversApp()); } class SliversApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( debugShowCheckedModeBanner: false, title: 'ShrinkWrap vs Slivers', home: Scaffold( appBar: AppBar( title: const Text("Revenge of the Slivers"), ), body: const ShrinkWrapSlivers(), ), ); } } class ShrinkWrapSlivers extends StatefulWidget { const ShrinkWrapSlivers({ Key? key, }) : super(key: key); @override _ShrinkWrapSliversState createState() => _ShrinkWrapSliversState(); } class _ShrinkWrapSliversState extends State<ShrinkWrapSlivers> { List<SliverList> innerLists = []; final numLists = 15; final numberOfItemsPerList = 100; @override void initState() { super.initState(); for (int i = 0; i < numLists; i++) { final _innerList = <ColorRow>[]; for (int j = 0; j < numberOfItemsPerList; j++) { _innerList.add(const ColorRow()); } innerLists.add( SliverList( delegate: SliverChildBuilderDelegate( (BuildContext context, int index) => _innerList[index], childCount: numberOfItemsPerList, ), ), ); } } @override Widget build(BuildContext context) { return CustomScrollView(slivers: innerLists); } } @immutable class ColorRow extends StatefulWidget { const ColorRow({Key? key}) : super(key: key); @override State createState() => ColorRowState(); } class ColorRowState extends State<ColorRow> { 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: <Widget>[ Padding( padding: const EdgeInsets.all(8.0), child: Container(height: 50, width: 50, color: Colors.white), ), Flexible( child: Column( children: const <Widget>[ Padding( padding: EdgeInsets.all(8), child: Text('这里是坚果前端小课堂!', style: TextStyle(color: Colors.white)), ), ], ), ), ], ), ); } } Color randomColor() => Color((math.Random().nextDouble() * 0xFFFFFF).toInt()).withOpacity(1.0); 复制代码
Lazy building!
上面的代码已经应用了这些更改。运行应用程序并注意 Flutter 不再需要立即渲染 100 个 ColorRow 小部件。当您滚动时,会动态构建更多小部件,正如您所期望的那样。更好的是,一直滚动到下一个列表也不会产生任何特殊费用。
Flutter 会根据需要重新构建小部件,而且很快。
这节课对你来说怎么样,可以的话,支持一下吧
你快速的滑动的时候会发现,这个时候的列表没有抖动!