6

In my database I have a user table where username, some marks are stored. I want to view that data in a table when user go to a particular page. So, when I go to that page at first the data(username and marks) doesn't show. But if I hot reload or use a button to refresh then the data shows properly. My question is how can I do that without hot reload or using a refresh button. Here is my code:

import 'package:flutter/material.dart';
import 'package:flutter_app/database/db_helper.dart';
import 'package:flutter_app/database/user.dart';

class ViewResult extends StatefulWidget {
 @override
 _ViewResult createState() => _ViewResult();
}

GlobalKey<ScaffoldState> scaffoldKey = new GlobalKey();

class _ViewResult extends State<ViewResult> {
 String tempEmail;
 bool check = true;

 var dbHelper;
 var data = List<User>();

 @override
 void initState() {
   setState(() {
     dbHelper = DBHelper();
     resultData();
   });
   super.initState();
 }

 void resultData() {
     dbHelper.getUser().then((users) {
       for (User temp in users) {
         if (temp.type == "student") data.add(temp);
       }
     });
 }

 @override
 Widget build(BuildContext context) {
   return Scaffold(
     appBar: AppBar(
       centerTitle: true,
       title: Text("Result"),
     ),
     body: DataTable(
       columnSpacing: 22,
       columns: [
         DataColumn(label: Text("Username")),
         DataColumn(label: Text("Beginner")),
         DataColumn(label: Text("Intermediate")),
         DataColumn(label: Text("Advanced")),
       ],
       rows: data
           .map((user) => DataRow(cells: [
                 DataCell(Text(user.email)),
                 DataCell(Text(user.beginnerMark.toString())),
                 DataCell(Text(user.intermediateMark.toString())),
                 DataCell(Text(user.advancedMark.toString())),
               ]))
           .toList(),
     ),
     backgroundColor: Color.fromRGBO(130, 178, 220, 1),
   );
 }
}

3 Answers3

5

TLDR: Call setState() from inside then() if not, it will be executed before everything completes and have no effect at all.

getUser().then((response) {
   //Your stuff

   setState(() {}); //refresh
  });
Petro
  • 3,484
  • 3
  • 32
  • 59
  • This is al right but problem with this approach is , it is building the whole page again which causes performance issue . Try doing this with any state management library instead. – Md omer arafat Nov 21 '21 at 06:15
  • @Mdomerarafat To mitigate the performance issue, create another custom stateful widget and use this code inside of that to only call setState on the widget you need to refresh – Petro Nov 22 '21 at 03:36
1

You have to use setState after you have loaded the data and your resultData functions is working with then, that is executed after the initial setState in the initState is finished.

@override
void initState() {
  // super.initState(); should be at the start of the method
  super.initState();
  dbHelper = DBHelper();
  resultData();
}

void resultData() {
  dbHelper.getUser().then((users) {
    for (User temp in users) {
      if (temp.type == "student") data.add(temp);
    }
    // since you have already added the results to data
    // setState can have an empty function body
    setState(() {});
  });
}

I prefer working with async/await instead of then so my solutions would be as follows:

Future<void> resultData() async {
  List<User> users = await dbHelper.getUser();
  setState(() {
    data = users.where((user) => user.type == "student");
  });
}
Dimitri L.
  • 4,499
  • 1
  • 15
  • 19
-2

You need setState(() {});. Add it near the end of resultData function:

void resultData() {
  dbHelper.getUser().then((users) {
     for (User temp in users) {
       if (temp.type == "student") data.add(temp);
     }
   setState(() {});
  });

}

See setState for more information.

DrFrancky
  • 1
  • 1
  • The `setState()` has to be called from inside `then()`, otherwise it will be executed first and have no effect at all. – Dimitri L. Dec 31 '19 at 14:27