如何使小部件工作得更快 - 自定义 json 转换小部件
How to make widget working faster - custom json convert widget
我有一个列表,我想在其中显示对象列表。每个对象都有一个 json 字段,其中定义了“标签”。每个都包含一个字段名和一个值。 json 中包含的字段的值必须以美观的“图块”形式显示。当一个字段获得焦点时,应显示字段名称(工具提示)。
我为此编写了可以转换 json 的小部件。工作正常,但我发现列表的性能随着项目数量的增加而降低很多(滚动并悬停在项目上)
10 岁还可以,但 50 岁就不行了。当我评论“JsonWidget”并只使用文本小部件时,一切都很快。不知道有没有更好的写法
她是完整代码:
import 'dart:convert';
import 'package:flutter/material.dart';
void main() {
runApp(GenistryApp());
}
//My example object with json field
class MyObject {
int id;
String json =
'{"year":1850,"1 name":"Zuzanna","names":"Stefania","surname":"Zabłocka","sex":"W","city":"Warsaw","date":"1850.01.02","father":"Piotr","mothers_anme":"Józefa","mothers_surname":"Wojnicz","info":"Szlachetni"}';
MyObject(this.id);
}
class GenistryApp extends StatelessWidget {
const GenistryApp({Key key}) : super(key: key);
@override
Widget build(BuildContext context) {
return MaterialApp(
home: MyTableWidget(),
theme: ThemeData(
primarySwatch: Colors.lightGreen,
visualDensity: VisualDensity.adaptivePlatformDensity,
));
}
}
class MyTableWidget extends StatefulWidget {
const MyTableWidget({Key key}) : super(key: key);
@override
_MyTableWidgetState createState() => _MyTableWidgetState();
}
class _MyTableWidgetState extends State<MyTableWidget> {
MyDataTableSource _data = MyDataTableSource([]);
List<MyObject> list = [];
//Generating 50 same elements for testing
getData() {
for (int i = 0; i < 50; i++) {
list.add(MyObject(i));
}
_data = MyDataTableSource(list);
}
@override
Widget build(BuildContext context) {
getData();
return Scaffold(
backgroundColor: Colors.white.withOpacity(0.8),
body: SingleChildScrollView(
scrollDirection: Axis.vertical,
child: PaginatedDataTable(
source: _data,
columns: [
DataColumn(label: Container()),
DataColumn(
label: ConstrainedBox(
constraints: BoxConstraints.expand(
width: MediaQuery.of(context).size.width))),
],
columnSpacing: 50,
horizontalMargin: 10,
rowsPerPage: 50,
showCheckboxColumn: false,
),
));
}
}
class MyDataTableSource extends DataTableSource {
List<MyObject> _data;
MyDataTableSource(this._data);
bool get isRowCountApproximate => false;
int get rowCount => _data.length;
int get selectedRowCount => 0;
DataRow getRow(int index) {
return DataRow(cells: [
DataCell(Text("ID")),
DataCell(
JsonWidget(_data[index]
.json), // Here is my widget to convert json field - it slows all list
// Text(_data[index].json), // Here is simple json field for testing - it works fast
onTap: () => {},
),
]);
}
}
//Widget to convert json to nice looking "tags"
class JsonWidget extends StatelessWidget {
String jdata;
Map<String, dynamic> data;
JsonWidget(String jdata) {
this.jdata = jdata;
}
var containers = <Tooltip>[];
@override
Widget build(BuildContext context) {
this.data = json.decode(this.jdata);
data.entries.forEach((element) {
containers.add(new Tooltip(
message: element.key, //tag's fieldname
textStyle: TextStyle(color: Colors.white),
child: Container(
margin: const EdgeInsets.all(3),
padding: const EdgeInsets.all(4),
child: Text(element.value.toString()), //tag's fieldvalue
decoration: BoxDecoration(
border: Border.all(color: Colors.blueAccent, width: 0.7),
borderRadius: BorderRadius.all(Radius.circular(20))),
)));
});
return Row(children: this.containers);
}
}
构建方法的设计方式应该是 pure/without 副作用。它应该只是 return 一个小部件,而不是 运行 for 循环,就像 JsonWidget 的情况一样。更好的编写方法是使用列表视图生成器。
class JsonWidget extends StatelessWidget {
Map<String, dynamic> data;
JsonWidget(Map<String, dynamic> data) {
this.data = data;
}
var containers = <Tooltip>[];
@override
Widget build(BuildContext context) {
return ListView.builder(
shrinkWrap: true,
scrollDirection: Axis.horizontal,
itemCount: data.entries.length,
itemBuilder: (context, index) {
return Tooltip(
message: data.entries.toList()[index].key, //tag's fieldname
textStyle: TextStyle(color: Colors.white),
child: Container(
margin: const EdgeInsets.all(3),
padding: const EdgeInsets.all(4),
child: Text(data.entries
.toList()[index]
.value
.toString()), //tag's fieldvalue
decoration: BoxDecoration(
border: Border.all(color: Colors.blueAccent, width: 0.7),
borderRadius: BorderRadius.all(Radius.circular(20))),
));
});
}
}
MyDataTableSoure 看起来像这样
class MyDataTableSource extends DataTableSource {
List<MyObject> _data;
MyDataTableSource(this._data);
bool get isRowCountApproximate => false;
int get rowCount => _data.length;
int get selectedRowCount => 0;
DataRow getRow(int index) {
return DataRow(cells: [
DataCell(Text("ID")),
DataCell(
JsonWidget(json.decode(_data[index]
.json)), // Here is my widget to convert json field - it slows all list
// Text(_data[index].json), // Here is simple json field for testing - it works fast
onTap: () => {},
),
]);
}
}
我有一个列表,我想在其中显示对象列表。每个对象都有一个 json 字段,其中定义了“标签”。每个都包含一个字段名和一个值。 json 中包含的字段的值必须以美观的“图块”形式显示。当一个字段获得焦点时,应显示字段名称(工具提示)。
我为此编写了可以转换 json 的小部件。工作正常,但我发现列表的性能随着项目数量的增加而降低很多(滚动并悬停在项目上) 10 岁还可以,但 50 岁就不行了。当我评论“JsonWidget”并只使用文本小部件时,一切都很快。不知道有没有更好的写法
她是完整代码:
import 'dart:convert';
import 'package:flutter/material.dart';
void main() {
runApp(GenistryApp());
}
//My example object with json field
class MyObject {
int id;
String json =
'{"year":1850,"1 name":"Zuzanna","names":"Stefania","surname":"Zabłocka","sex":"W","city":"Warsaw","date":"1850.01.02","father":"Piotr","mothers_anme":"Józefa","mothers_surname":"Wojnicz","info":"Szlachetni"}';
MyObject(this.id);
}
class GenistryApp extends StatelessWidget {
const GenistryApp({Key key}) : super(key: key);
@override
Widget build(BuildContext context) {
return MaterialApp(
home: MyTableWidget(),
theme: ThemeData(
primarySwatch: Colors.lightGreen,
visualDensity: VisualDensity.adaptivePlatformDensity,
));
}
}
class MyTableWidget extends StatefulWidget {
const MyTableWidget({Key key}) : super(key: key);
@override
_MyTableWidgetState createState() => _MyTableWidgetState();
}
class _MyTableWidgetState extends State<MyTableWidget> {
MyDataTableSource _data = MyDataTableSource([]);
List<MyObject> list = [];
//Generating 50 same elements for testing
getData() {
for (int i = 0; i < 50; i++) {
list.add(MyObject(i));
}
_data = MyDataTableSource(list);
}
@override
Widget build(BuildContext context) {
getData();
return Scaffold(
backgroundColor: Colors.white.withOpacity(0.8),
body: SingleChildScrollView(
scrollDirection: Axis.vertical,
child: PaginatedDataTable(
source: _data,
columns: [
DataColumn(label: Container()),
DataColumn(
label: ConstrainedBox(
constraints: BoxConstraints.expand(
width: MediaQuery.of(context).size.width))),
],
columnSpacing: 50,
horizontalMargin: 10,
rowsPerPage: 50,
showCheckboxColumn: false,
),
));
}
}
class MyDataTableSource extends DataTableSource {
List<MyObject> _data;
MyDataTableSource(this._data);
bool get isRowCountApproximate => false;
int get rowCount => _data.length;
int get selectedRowCount => 0;
DataRow getRow(int index) {
return DataRow(cells: [
DataCell(Text("ID")),
DataCell(
JsonWidget(_data[index]
.json), // Here is my widget to convert json field - it slows all list
// Text(_data[index].json), // Here is simple json field for testing - it works fast
onTap: () => {},
),
]);
}
}
//Widget to convert json to nice looking "tags"
class JsonWidget extends StatelessWidget {
String jdata;
Map<String, dynamic> data;
JsonWidget(String jdata) {
this.jdata = jdata;
}
var containers = <Tooltip>[];
@override
Widget build(BuildContext context) {
this.data = json.decode(this.jdata);
data.entries.forEach((element) {
containers.add(new Tooltip(
message: element.key, //tag's fieldname
textStyle: TextStyle(color: Colors.white),
child: Container(
margin: const EdgeInsets.all(3),
padding: const EdgeInsets.all(4),
child: Text(element.value.toString()), //tag's fieldvalue
decoration: BoxDecoration(
border: Border.all(color: Colors.blueAccent, width: 0.7),
borderRadius: BorderRadius.all(Radius.circular(20))),
)));
});
return Row(children: this.containers);
}
}
构建方法的设计方式应该是 pure/without 副作用。它应该只是 return 一个小部件,而不是 运行 for 循环,就像 JsonWidget 的情况一样。更好的编写方法是使用列表视图生成器。
class JsonWidget extends StatelessWidget {
Map<String, dynamic> data;
JsonWidget(Map<String, dynamic> data) {
this.data = data;
}
var containers = <Tooltip>[];
@override
Widget build(BuildContext context) {
return ListView.builder(
shrinkWrap: true,
scrollDirection: Axis.horizontal,
itemCount: data.entries.length,
itemBuilder: (context, index) {
return Tooltip(
message: data.entries.toList()[index].key, //tag's fieldname
textStyle: TextStyle(color: Colors.white),
child: Container(
margin: const EdgeInsets.all(3),
padding: const EdgeInsets.all(4),
child: Text(data.entries
.toList()[index]
.value
.toString()), //tag's fieldvalue
decoration: BoxDecoration(
border: Border.all(color: Colors.blueAccent, width: 0.7),
borderRadius: BorderRadius.all(Radius.circular(20))),
));
});
}
}
MyDataTableSoure 看起来像这样
class MyDataTableSource extends DataTableSource {
List<MyObject> _data;
MyDataTableSource(this._data);
bool get isRowCountApproximate => false;
int get rowCount => _data.length;
int get selectedRowCount => 0;
DataRow getRow(int index) {
return DataRow(cells: [
DataCell(Text("ID")),
DataCell(
JsonWidget(json.decode(_data[index]
.json)), // Here is my widget to convert json field - it slows all list
// Text(_data[index].json), // Here is simple json field for testing - it works fast
onTap: () => {},
),
]);
}
}