Flutter [ Datatable ]

Asked

Viewed 106 times

-1

I am new to Flutter programming. I have assembled a page that when calling via menu I would like to present the data in a Datatable.

I even managed to do this, but only presents the data when I click to change the order, I should present the data right when opening the screen.

I will post here as mounted, if you can give a strength. I thank from now!

import 'dart:convert';

import 'package:cibernetica/screens/modelDiscip.dart';
import 'package:flutter/material.dart';
import 'package:cibernetica/screens/loginuser.dart';
import 'package:http/http.dart' as http;

class pagdisciplina extends StatefulWidget {
var oTbAluno;
pagdisciplina({this.oTbAluno});

@override
_pagdisciplinaState createState() => _pagdisciplinaState();
}

class _pagdisciplinaState extends State<pagdisciplina> {
var id = ModelDiscip.id;
List<ModelDiscip> tbDiscip;
bool sort;

@override
void initState() {
sort = false;

setState(() {
  var tbtmp = getDisciplina(id);
  tbDiscip = getConvert(tbtmp);
});
super.initState();
}

onSortColum(int columnIndex, bool ascending) {
if (columnIndex == 0) {
if (ascending) {
setState(() {
tbDiscip.sort((a, b) => a.disciplina.compareTo(b.disciplina));
});
} else {
setState(() {
tbDiscip.sort((a, b) => b.disciplina.compareTo(a.disciplina));
});
}
}
}

DataTable dataBody() {
return DataTable(
sortAscending: sort,
sortColumnIndex: 0,
columns: [
DataColumn(
label: Text("Disciplina"),
numeric: false,
tooltip: "Nome da disciplina",
onSort: (columnIndex, ascending) {
setState(() {
sort = !sort;
});
onSortColum(columnIndex, ascending);
}),
DataColumn(
label: Text("Professor"),
numeric: false,
tooltip: "Professor da disciplina")
],
rows: tbDiscip
.map(
// ignore: non_constant_identifier_names
(ModelDiscip) => DataRow(cells: [
DataCell(Text(ModelDiscip.disciplina), onTap: () {
print('Selecionado ${ModelDiscip.disciplina}');
}),
DataCell(
Text(ModelDiscip.professor),
),
]),
)
.toList(),
);
}

@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Disciplinas'),
),
body: Column(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.center,
verticalDirection: VerticalDirection.down,
children: <Widget>[
Center(
child: dataBody(),
)
],
),
);
}

listaTrabalhos() {
return ListView.builder(
itemBuilder: (context, index) {
return ListTile(
title: Text(''),
);
},
);
}

static Future<List<dynamic>> getDisciplina(int id) async {
String url =
'http://facbrasil.com/mobile/educacional/trabalho/' + id.toString();
final response = await http.get(
url,
headers: {'Content-Type': 'application/json; charset=UTF-8'},
);
var convDataToJson = jsonDecode(response.body);
List<dynamic> listaDiscip = new List<dynamic>();

for (Map<String, dynamic> json in convDataToJson) {
  ModelDiscip lista = ModelDiscip.fromJson(json);
  listaDiscip.add(lista);
}
return listaDiscip;
}

List<ModelDiscip> getConvert(Future<List<dynamic>> oLista) {
List<ModelDiscip> listConvert = [];
oLista.then((value) =>
{if (value != null) value.forEach((item) => listConvert.add(item))});
return listConvert == null ? [] : listConvert;
}

1 answer

0

No sense in calling setState inside initState, because the state is only built after the initState ends, and the setState serves to "warn" Flutter that the state has changed (as it may have changed if it has not even been built yet?).

Now, let’s talk about the function getConvert: she’s synchronous, so she returns before of the function then, that returns a Future, be actually computed. Therefore, at the time of return of getConvert, the list listConvert is always empty... I strongly recommend that you study the tutorial on calmly asynchronous programming of Dart, as it is not an easy thing for beginners.

What you want is to wait for the function passed to the then is executed before getConvert end. So, you need to use the await and change the return of getConvert for Future<List<ModelDiscip>>:

Future<List<ModelDiscip>> getConvert(Future<List<dynamic>> oLista) async {
List<ModelDiscip> listConvert = [];
await oLista.then((value) =>
{if (value != null) value.forEach((item) => listConvert.add(item))});
return listConvert == null ? [] : listConvert;
}

There is another question: perform a function asynchronous as soon as the screen opens. For this, you can use the function addPostFrameCallback. The initState would look like this (note await before getConvert, that returns a uture):

@override
void initState() {
    sort = false;
    WidgetsBinding.instance.addPostFrameCallback((_) async {
        var tbtmp = getDisciplina(id);
        tbDiscip = await getConvert(tbtmp);
    });
    super.initState();
}

Finally, some style tips: do not abuse the var nor names of abbreviated variables; they make it difficult to read. An example is the line var tbtmp = getDisciplina(id);: there’s no way of knowing what it is tbtmp without sneaking out the rest of the code.

  • Josenaldo, good evening. Thanks for the feedback and the tips. I will make these adjustments that scored and answer as soon as finalize the adjustments.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.