FutureBuilder: snapshot.hasdata всегда false - PullRequest
0 голосов
/ 25 февраля 2019

Я пытаюсь заполнить ListView информацией об учетной записи, которую получают из базы данных Sqflite.Вот как я читаю данные учетной записи из базы данных:

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 [];

Это то, как я пытаюсь создать представление списка, используя 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');
      }
    );
  }
}

Пользовательская модель данных определяется следующим образом:

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
    };
  }
}

Моя проблема в том, что, хотя база данных хранит действительные данные, а также метод getAllAccounts(), похоже, возвращает действительные данные, оператор snapshot.hasdata внутри виджета FutureBuilder также всегдаis false .

Что здесь не так?

С консоли:

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']

(Последняя строка этого фрагмента из консоли соответствуетс оператором печати в конце метода "getAllAccounts".)

1 Ответ

0 голосов
/ 25 февраля 2019

Я решил проблему:

В поставщике базы данных в методе "getAllAccounts () мне пришлось явно объявить тип объекта учетных записей следующим образом:

List<AccountModel> accounts = [];
...