I'm trying to fill a ListView with account information, which gets fetched from a Sqflite database. Here is how I read the account data from db:
dbhelper.dart
Future<List<AccountModel>> getAllAccounts() async {
final dbClient = await db;
print('getAllAccounts');
List<Map> res = await dbClient.rawQuery('SELECT * FROM Accounts');
if (res.isNotEmpty) {
print('Accounts $res');
var accounts = [];
for (var i = 0; i < res.length; i++) {
var account =AccountModel.fromDb(res[i]);
print('Account $account');
accounts.add(account);
}
print('Return $accounts');
return accounts;
}
return [];
This is, how I try to contruct the list view, using the FutureBuilder-Widget:
account_list_widget.dart
class AccountList extends StatefulWidget {
State<StatefulWidget> createState() {
return AccountListState();
}
}
class AccountListState extends State<AccountList> {
@override
Widget build(BuildContext context) {
return Stack(
children: <Widget>[
FutureBuilder<List<AccountModel>>(
future: DbProvider().getAllAccounts(),
builder: (BuildContext context, AsyncSnapshot<List<AccountModel>> snapshot) {
if (snapshot.hasData) {
return Stack(
children: <Widget>[
ListView.builder(
itemCount: snapshot.data.length + 1,
itemBuilder: (BuildContext context, int index) {
if (index == 0) {
return ListSectionHeader('Konten');
} else {
// Korrigieren des Index, da ja die 0 schon "verbraucht" wurde,
// auf die Daten aber weiterhhin mit Start-Index 0 zugegriffen wird.
index--;
AccountModel account = snapshot.data[index];
return Dismissible(
key: UniqueKey(),
background: Container(color: Colors.red),
onDismissed: (direction) {
DbProvider().removeAccount(account.uuid);
},
child: ListTile(
title: Text(account.accountName),
leading: Icon(Icons.crop_square),
trailing: Icon(Icons.keyboard_arrow_right),
),
);
}
},
),
addAccountTile()
],
);
} else {
return ListView.builder(
itemCount: 2,
itemBuilder: (BuildContext context, int index) {
if (index == 0) {
return ListSectionHeader('Konten2');
} else {
return addAccountTile();
}
},
);
}
},
),
],
);
}
Widget addAccountTile() {
return ListTile(
title: Text('Neues Konto hinzufügen'),
leading: Icon(
Icons.add_circle,
color: Colors.blue,
),
trailing: Icon(Icons.keyboard_arrow_right),
onTap: () {
Navigator.pushNamed(context, '/newaccount');
}
);
}
}
The custom data model is defined like this:
account_model.dart
class AccountModel {
final String uuid;
final String accountName;
final String host;
final String userName;
final String password;
final String lastConnected;
final bool active;
final bool useHeadset;
AccountModel(this.uuid, this.accountName, this.host, this.userName,
this.password, this.lastConnected, this.active, this.useHeadset);
AccountModel.fromJson(Map<String, dynamic> parsedJson)
: uuid = parsedJson['uuid'],
accountName = parsedJson['accountName'],
host = parsedJson['host'],
userName = parsedJson['userName'],
password = parsedJson['password'],
lastConnected = parsedJson['lastConnected'],
active = parsedJson['active'],
useHeadset = parsedJson['useHeadset'];
AccountModel.fromDb(Map<String, dynamic> parsedJson)
: uuid = parsedJson['uuid'],
accountName = parsedJson['accountName'],
host = parsedJson['host'],
userName = parsedJson['userName'],
password = parsedJson['password'],
lastConnected = parsedJson['lastConnected'],
active = parsedJson['active'] == 1,
useHeadset = parsedJson['useHeadset'] == 1;
Map<String, dynamic> toMap() {
return <String, dynamic> {
'uuid': uuid,
'accountName': accountName,
'host': host,
'userName': userName,
'password': password,
'lastConnected': lastConnected,
'active': active ? 1 : 0,
'useHeadset': useHeadset ? 1 : 0
};
}
}
My problem is, that although the database stores valid data and also the method getAllAccounts()
seems to return valid data, the statement snapshot.hasdata
inside the FutureBuilder widget alsways is false.
What goes wrong here?
From the console:
D/Sqflite ( 9179): [Thread[main,5,main]] opened 6 /data/user/0/com.example.dashboard/app_flutter/test.db total open count (6)
D/Sqflite ( 9179): [Thread[Sqflite,5,main]] BEGIN EXCLUSIVE
D/Sqflite ( 9179): [Thread[Sqflite,5,main]] PRAGMA user_version;
D/Sqflite ( 9179): [Thread[Sqflite,5,main]] PRAGMA user_version = 1;
D/Sqflite ( 9179): [Thread[Sqflite,5,main]] COMMIT
I/flutter ( 9179): getAllAccounts
D/Sqflite ( 9179): [Thread[Sqflite,5,main]] SELECT * FROM Accounts
I/flutter ( 9179): Accounts [{uuid: 436f2c10-3260-11e9-fe03-65fdfe3a7bbd, accountName: 12345, host: 12345, userName: 12345, password: 12345, lastConnected: 0, active: 0, useHeadset: 0}]
I/flutter ( 9179): Account Instance of 'AccountModel'
I/flutter ( 9179): Return [Instance of 'AccountModel']
(The last line of this snippet from the console corresponds with the print statement at the end of the "getAllAccounts" method.)
print('snapshot: $snapshot');
beforeif (snapshot.hasData) {
, what do you see? – pskinksnapshot: AsyncSnapshot<List<AccountModel>>(ConnectionState.done, [], null)
– rweinbrecherprint('snapshot data: ${snapshot.data}');
? is it:snapshot data: []
? – pskinksnapshot data: []
– rweinbrechergetAllAccounts()
method returned empty list (return [];
) but stillsnapshot.hasData
should betrue
– pskink