Reputation: 602
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
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
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