我需要创建一个52x80的正方形方块网格。看起来像这样:
但是在仿真器中开发时性能特别慢(超过1秒的“滞后”)。我了解Flutter代码在物理设备上的发布模式下运行得更快,在我的情况下,如果设备是新设备,也是如此。但是,如果设备使用了几年(例如,三星Galaxy S8或iPhone 8),则在加载视图和滚动时会有令人沮丧的明显时间。而且我不能那样发布我的应用程序。我正在这样构建GridView:
GridView.count(
shrinkWrap: true,
primary: false,
padding: const EdgeInsets.all(5.0),
crossAxisCount: 52,
crossAxisSpacing: 1.0,
mainAxisSpacing: 1.0,
addAutomaticKeepAlives: true,
children: blocks.map((block) => // blocks is just a list of 4160 objects
FlatButton(
child: null,
color: block.backgroundColor,
onPressed: () {
// open a new route
},
splashColor: Colors.transparent,
highlightColor: Colors.transparent
)
).toList()
)
我尝试将FlatButton
换成Image
或SizedBox
,这会有所帮助。关于如何提高速度的任何建议?
答案 0 :(得分:3)
如果您需要向团伙添加onTap行为,则可以使用CustomPainter小部件创建自己的CustomGridView,并绘制所有项目并添加一个手势检测器并计算触摸位置
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: Scaffold(
backgroundColor: Colors.black,
body: SafeArea(
child: MyHomePage(),
),
),
);
}
}
final int redCount = 728;
final int greyCount = 3021;
final int allCount = 4160;
final int crossAxisCount = 52;
enum BlockTypes {
red,
gray,
green,
yellow,
}
class MyHomePage extends StatefulWidget {
MyHomePage()
: blocks = List<BlockTypes>.generate(allCount, (index) {
if (index < redCount) {
return BlockTypes.red;
} else if (index < redCount + greyCount) {
return BlockTypes.gray;
}
return BlockTypes.green;
});
final List<BlockTypes> blocks;
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
int columnsCount;
double blocSize;
int clickedIndex;
Offset clickOffset;
bool hasSizes = false;
List<BlockTypes> blocks;
final ScrollController scrollController = ScrollController();
@override
void initState() {
WidgetsBinding.instance.addPostFrameCallback(_afterLayout);
blocks = widget.blocks;
super.initState();
}
void _afterLayout(_) {
blocSize = context.size.width / crossAxisCount;
columnsCount = (allCount / crossAxisCount).ceil();
setState(() {
hasSizes = true;
});
}
void onTapDown(TapDownDetails details) {
final RenderBox box = context.findRenderObject();
clickOffset = box.globalToLocal(details.globalPosition);
}
void onTap() {
final dx = clickOffset.dx;
final dy = clickOffset.dy + scrollController.offset;
final tapedRow = (dx / blocSize).floor();
final tapedColumn = (dy / blocSize).floor();
clickedIndex = tapedColumn * crossAxisCount + tapedRow;
setState(() {
blocks[clickedIndex] = BlockTypes.yellow;
});
}
@override
Widget build(BuildContext context) {
print(blocSize);
return hasSizes
? SingleChildScrollView(
controller: scrollController,
child: GestureDetector(
onTapDown: onTapDown,
onTap: onTap,
child: CustomPaint(
size: Size(
MediaQuery.of(context).size.width,
columnsCount * blocSize,
),
painter: CustomGridView(
blocs: widget.blocks,
columnsCount: columnsCount,
blocSize: blocSize,
),
),
),
)
: Container();
}
}
class CustomGridView extends CustomPainter {
final double gap = 1;
final Paint painter = Paint()
..strokeWidth = 1
..style = PaintingStyle.fill;
final int columnsCount;
final double blocSize;
final List<BlockTypes> blocs;
CustomGridView({this.columnsCount, this.blocSize, this.blocs});
@override
void paint(Canvas canvas, Size size) {
blocs.asMap().forEach((index, bloc) {
setColor(bloc);
canvas.drawRRect(
RRect.fromRectAndRadius(
Rect.fromLTWH(
getLeft(index),
getTop(index),
blocSize - gap,
blocSize - gap,
),
Radius.circular(1.0)),
painter);
});
}
double getTop(int index) {
return (index / crossAxisCount).floor().toDouble() * blocSize;
}
double getLeft(int index) {
return (index % crossAxisCount).floor().toDouble() * blocSize;
}
@override
bool shouldRepaint(CustomGridView oldDelegate) => true;
@override
bool shouldRebuildSemantics(CustomGridView oldDelegate) => true;
void setColor(BlockTypes bloc) {
switch (bloc) {
case BlockTypes.red:
painter.color = Colors.red;
break;
case BlockTypes.gray:
painter.color = Colors.grey;
break;
case BlockTypes.green:
painter.color = Colors.green;
break;
case BlockTypes.yellow:
painter.color = Colors.yellow;
break;
}
}
}
答案 1 :(得分:0)
答案 2 :(得分:0)
GridView.builder()
非常适合生成包含大量项目的网格视图。
在这种情况下,使用GridView.count
效率不高。而是使用GridView.builder
,它将提高性能,因为将根据需要生成项目。
查看官方文件
GridView.builder构造可创建一个可滚动的2D窗口小部件数组,这些数组按需创建。 该构造函数适用于具有大量(或无限个)子级的网格视图,因为仅针对那些实际可见的子级调用该构建器。
请参见下面的示例代码:
GridView.builder(
gridDelegate: new SliverGridDelegateWithFixedCrossAxisCount(
// number of items on a row
crossAxisCount: 52,
// horizontal spacing between items
crossAxisSpacing: 3,
// vertical spacing between items
mainAxisSpacing: 5,
),
itemBuilder: (BuildContext context, int index) {
// your list of objects here
return blocks();
},
),
我希望这会有所帮助。