mercredi 24 novembre 2021

How to make widget working faster - custom json convert widget

I have a list where I want to display a list of objects. Each object has a json field where "tags" are defined. Each consists of a field name and a value. The values from the fields contained in json have to be displayed in a nice looking form of "tiles". When a field is focused, the field name (ToolTip) should appears.

I wrote my widget that converts json for this. Works fine, but I've found that performance of list slows down much with number of items (scrolling and hovering over an item) At 10 it is still ok, but at 50 it's not. When I comment "JsonWidget" and just use Text widget, everything works fast. I wonder if there is a way to write it in a more optimal way.

Her is full code:

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);
  }
}




Aucun commentaire:

Enregistrer un commentaire