Flutter ListView 在 Container Lazy Rendering 和性能上的表现
Flutter ListView in Container Lazy Rendering and performance
我有一长串经常更新的项目。该列表使用 ListView.builder 包裹在容器中以应用边框等呈现。
我的问题是,当 ListView 位于容器中时,会呈现所有项目,包括屏幕外的元素。由于列表经常重绘,严重影响性能。
我创建了两个例子来说明这个问题。为了简单起见,示例是无状态的,在现实生活中列表是有状态的。
示例 1 - ListView 是根小部件。请注意,在控制台中只构建了可见的卡片。
https://dartpad.dev/ac436b786ae48383c107a64bb3db8070
示例 2 - ListView 包装在容器中。注意所有卡片都已构建。
https://dartpad.dev/109f1f97085c1726c0826f6ea8b731ec
如何制作一个带有项目列表的可滚动容器,它只呈现可见项目?
示例2的来源:
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
MyApp({Key key}) : super(key: key);
@override
Widget build(BuildContext context) {
return MaterialApp(
home: SingleChildScrollView(
child: Container(
color: Colors.green,
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Container(
width: 700,
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(10),
boxShadow: [
BoxShadow(
color: Colors.black.withOpacity(0.44),
spreadRadius: 0,
blurRadius: 15,
offset:
Offset(0, 1), // changes position of shadow
),
]),
margin: EdgeInsets.all(24.0),
child: Container(
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
ListView.builder(
scrollDirection: Axis.vertical,
shrinkWrap: true,
itemCount: 20,
itemBuilder: (context, index) {
var text = 'Card $index';
print('Building card $text');
return Card(
child: Container(
height: 130,
child: Center(
child: Text(text),
)));
})
]))),
],
))));
}
}
你应该给包裹在容器中的listView一个高度限制。
就像这样:
class MyApp extends StatelessWidget {
MyApp({Key key}) : super(key: key);
@override
Widget build(BuildContext context) {
return MaterialApp(
home: SingleChildScrollView(
child: Container(
color: Colors.green,
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Container(
width: 700,
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(10),
boxShadow: [
BoxShadow(
color: Colors.black.withOpacity(0.44),
spreadRadius: 0,
blurRadius: 15,
offset:
Offset(0, 1),
),
]),
margin: EdgeInsets.all(24.0),
child: Container(
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
SizedBox( // add a SizedBox and set a specific height
height: 1000,
child: ListView.builder(
scrollDirection: Axis.vertical,
shrinkWrap: true,
itemCount: 20,
itemBuilder: (context, index) {
var text = 'Card $index';
print('testtest Building card $text');
return Card(
child: Container(
height: 130,
child: Center(
child: Text(text),
)));
}),
)
]))),
],
))));
}
}
我有一长串经常更新的项目。该列表使用 ListView.builder 包裹在容器中以应用边框等呈现。
我的问题是,当 ListView 位于容器中时,会呈现所有项目,包括屏幕外的元素。由于列表经常重绘,严重影响性能。
我创建了两个例子来说明这个问题。为了简单起见,示例是无状态的,在现实生活中列表是有状态的。
示例 1 - ListView 是根小部件。请注意,在控制台中只构建了可见的卡片。 https://dartpad.dev/ac436b786ae48383c107a64bb3db8070
示例 2 - ListView 包装在容器中。注意所有卡片都已构建。 https://dartpad.dev/109f1f97085c1726c0826f6ea8b731ec
如何制作一个带有项目列表的可滚动容器,它只呈现可见项目?
示例2的来源:
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
MyApp({Key key}) : super(key: key);
@override
Widget build(BuildContext context) {
return MaterialApp(
home: SingleChildScrollView(
child: Container(
color: Colors.green,
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Container(
width: 700,
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(10),
boxShadow: [
BoxShadow(
color: Colors.black.withOpacity(0.44),
spreadRadius: 0,
blurRadius: 15,
offset:
Offset(0, 1), // changes position of shadow
),
]),
margin: EdgeInsets.all(24.0),
child: Container(
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
ListView.builder(
scrollDirection: Axis.vertical,
shrinkWrap: true,
itemCount: 20,
itemBuilder: (context, index) {
var text = 'Card $index';
print('Building card $text');
return Card(
child: Container(
height: 130,
child: Center(
child: Text(text),
)));
})
]))),
],
))));
}
}
你应该给包裹在容器中的listView一个高度限制。 就像这样:
class MyApp extends StatelessWidget {
MyApp({Key key}) : super(key: key);
@override
Widget build(BuildContext context) {
return MaterialApp(
home: SingleChildScrollView(
child: Container(
color: Colors.green,
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Container(
width: 700,
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(10),
boxShadow: [
BoxShadow(
color: Colors.black.withOpacity(0.44),
spreadRadius: 0,
blurRadius: 15,
offset:
Offset(0, 1),
),
]),
margin: EdgeInsets.all(24.0),
child: Container(
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
SizedBox( // add a SizedBox and set a specific height
height: 1000,
child: ListView.builder(
scrollDirection: Axis.vertical,
shrinkWrap: true,
itemCount: 20,
itemBuilder: (context, index) {
var text = 'Card $index';
print('testtest Building card $text');
return Card(
child: Container(
height: 130,
child: Center(
child: Text(text),
)));
}),
)
]))),
],
))));
}
}