这是我参与11月更文挑战的第22天,活动详情查看:2021最后一次更文挑战
这里是坚果前端小课堂,大家喜欢的话,可以关注我的公众号“坚果前端,”,或者加我好友,获取更多精彩内容
重新构建嵌套列表
我们接着上一期的继续今天的 内容
使用 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 会根据需要重新构建小部件,而且很快。
这节课对你来说怎么样,可以的话,支持一下吧
你快速的滑动的时候会发现,这个时候的列表没有抖动!