Abdulaziz Yesuf
Abdulaziz Yesuf

Reputation: 602

List not being updated when list updated from initState()

I have an sqlite database called people.db and I am trying to list all the date in the people table. I am rendering the date list which is first initialized as an empty list. This list is later filled with the data retrieved from the database in the fetchDate() method which is called in the initState().Here is the full code:

import 'package:flutter/material.dart';
import 'package:sqflite/sqflite.dart';
import 'package:path/path.dart';

class ListPerson extends StatefulWidget{
  @override
  State<StatefulWidget> createState() {
    return ListPersonState();
  } 
}

class ListPersonState extends State<ListPerson>{

  List<Map> date = [];
  List<Map<String, dynamic>> temp = [];
  List<Map<String, dynamic>> people = [];

  void fetchDate() async{
    var databasesPath = await getDatabasesPath();
    String path = join(databasesPath, "people.db");

    Database db;
    db = await openDatabase(path, version: 1);

    date = await db.rawQuery("SELECT DISTINCT date FROM people");
    for (var i = 0; i < people.length; i++) {
      print(people[i]);
    }
    fetchPeople(date);

  }

  void fetchPeople(List<Map> date) async{
    var databasesPath = await getDatabasesPath();
    String path = join(databasesPath, "people.db");

    Database db;
    db = await openDatabase(path, version: 1);

    for(int i=0; i< date.length; i++){
      temp.addAll(await db.rawQuery("SELECT * FROM people WHERE date == '${date[i]['date']}'")) ;
      people.add(temp[i]);
    }
  }

  @override
  void initState(){
    super.initState();
    fetchDate();
  }
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Center(
          child: Text(
            "Added People",
            style: TextStyle(
              color: Colors.white,
              fontFamily: 'Montserrat',
              fontWeight: FontWeight.bold),
          ),
        ),
      ),
      body: Container(
        child: Column(
          children: <Widget>[
            Expanded(
              child: ListView.builder(
                scrollDirection: Axis.vertical,
                shrinkWrap: true,
                itemCount: date.length,
                itemBuilder: (BuildContext context, int index){
                  return Card(
                    color: Colors.white,
                    child: Padding(
                      padding: EdgeInsets.symmetric(vertical: 24.0, horizontal: 16.0),
                      child: Center(
                        child: ListTile(
                          title: Text(date[index]['date']),

                        )
                      ) 
                    ),
                  );
                },
              ),
            )
          ],
        )
      )
    );
  }

  dropClicked() {}

}

I expected to see all the dates (currently 2) in a list of cards. But it shows me an empty page. I added the print statements in the fetchDate() method to check if the data is being fetched from the database correctly and it is. I don't know why the list is being shown. Any help would be appreciated. Thank you in advance.

Upvotes: 0

Views: 950

Answers (2)

Sagar Acharya
Sagar Acharya

Reputation: 3777

As you have checked then that's ok but I will just post as I just created an example for you As you are in the async await mode so UI must do some of the tasks so that it will know if it's loading the data or data is loaded. I have made some changes in your code created assigned a boolean which in UI will show if the data is loading (CircularProgressIndicator). And If data is loaded then you will get the desired widget.

import 'package:flutter/material.dart';
import 'package:sqflite/sqflite.dart';
import 'package:path/path.dart';

class ListPerson extends StatefulWidget {
  @override
  State<StatefulWidget> createState() {
    return ListPersonState();
  }
}

class ListPersonState extends State<ListPerson> {
  List<Map> date = [];
  List<Map<String, dynamic>> temp = [];
  List<Map<String, dynamic>> people = [];
  bool _isLoading = false;

  void fetchDate() async {
    setState(() {
      _isLoading = true;
    });
    var databasesPath = await getDatabasesPath();
    String path = join(databasesPath, "people.db");

    Database db;
    db = await openDatabase(path, version: 1);

    date = await db.rawQuery("SELECT DISTINCT date FROM people");
    for (var i = 0; i < people.length; i++) {
      print(people[i]);
    }
    fetchPeople(date);
  }

  void fetchPeople(List<Map> date) async {
    var databasesPath = await getDatabasesPath();
    String path = join(databasesPath, "people.db");

    Database db;
    db = await openDatabase(path, version: 1);

    for (int i = 0; i < date.length; i++) {
      temp.addAll(await db
          .rawQuery("SELECT * FROM people WHERE date == '${date[i]['date']}'"));
      people.add(temp[i]);
    }
    setState(() {
      _isLoading = false;
    });
  }

  @override
  void initState() {
    super.initState();
    fetchDate();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          title: Center(
            child: Text(
              "Added People",
              style: TextStyle(
                  color: Colors.white,
                  fontFamily: 'Montserrat',
                  fontWeight: FontWeight.bold),
            ),
          ),
        ),
        body: _isLoading
            ? Center(
              // this will show the laoding untill you load the data
                child: CircularProgressIndicator(),
              )
            : Container(
                child: Column(
                children: <Widget>[
                  Expanded(
                    child: ListView.builder(
                      scrollDirection: Axis.vertical,
                      shrinkWrap: true,
                      itemCount: date.length,
                      itemBuilder: (BuildContext context, int index) {
                        return Card(
                          color: Colors.white,
                          child: Padding(
                              padding: EdgeInsets.symmetric(
                                  vertical: 24.0, horizontal: 16.0),
                              child: Center(
                                  child: ListTile(
                                title: Text(date[index]['date']),
                              ))),
                        );
                      },
                    ),
                  )
                ],
              )));
  }

  dropClicked() {}
}

Upvotes: 0

Victor Eronmosele
Victor Eronmosele

Reputation: 7726

This list is not shown because you're doing an async operation and the widget is already built by the time your async operation is complete.

You should call setState right after fetchPeople(date) in fetchDate(). This "notif[ies] the framework that the internal state of this object has changed."

And you should also add an await to the fetchPeople call so setState gets called only when the operation is complete.

So instead of

void fetchDate() async{
    //Other methods
    fetchPeople(date);
  }

you have :

void fetchDate() async{
    //Other methods
   await fetchPeople(date);
   setState((){});
  }

Upvotes: 3

Related Questions