从数据库读取异步时未显示我的列表

时间:2019-09-26 19:06:48

标签: flutter

我有一个正在从数据库表(sqllite)读取数据的屏幕,但是该数据未显示在我的列表视图中。看起来当我读取数据时,屏幕已经显示gui了,并且当listview访问数组时,我的数组还没有填充数据。 下面是我的代码

import 'package:finsec/model/cardview_list_item.dart';
import 'package:flutter/material.dart';
import 'package:finsec/utils/strings.dart';
import 'package:finsec/utils/colors.dart';
import 'package:finsec/widget/circle_icon.dart';
import 'package:finsec/data/db_provider.dart';
import 'package:sqflite/sqflite.dart';
import 'package:finsec/utils/queries.dart';

class CardviewListItemData  extends StatefulWidget {
  @override
  State<StatefulWidget> createState() {

    return CardviewListItemDataState();
  }
}

class CardviewListItemDataState extends State<CardviewListItemData> {
  DBProvider db = new DBProvider();
  List<String> amountList;
  List<CardviewListItem> listItems  = List<CardviewListItem>();
  int count = 0;

  @override
  Widget build(BuildContext context) {
    if (amountList == null) {
      amountList = List<String>();

      updateListView();
      listItems = summaryList();

    }

    return ListView.builder(
      itemCount: listItems.length,
      shrinkWrap: true,
      itemBuilder: (context, index) {
        return ListTile(
          leading: Icon(listItems[index].icon, color: listItems[index].iconColor),
          title: Align(
            child: new Text(listItems[index].title,style: TextStyle(fontSize: 16)),
            alignment: Alignment(-1.4, 0),
          ),
          trailing: new Text(listItems[index].amount, style: TextStyle(fontSize: 16),),
          //onTap: () => onTapped(context, listItems[index].title),
        );
      },
    );
  }
  List<CardviewListItem> summaryList() {


    List<CardviewListItem> summaryListItems = List<CardviewListItem>();
    CardviewListItem income = new CardviewListItem(
        title: totalIncome,
        amount: amountList[0],
        icon: Icons.attach_money,
        iconColor: green

    );
    summaryListItems.add(income);


    return summaryListItems;
  }



  void updateListView() {
    final Future<Database> dbFuture = db.initializeDatabase();
    dbFuture.then((database) {

      Future<List<String>> incomeListFuture = db.getDataList(test);
      incomeListFuture.then((amountList) {
        setState(() {
          this.amountList = amountList;
          this.count = this.amountList.length;
        });
      });
    });
  }


}

我的数据库代码是

import 'dart:io';
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:path_provider/path_provider.dart';
import 'package:path/path.dart';
import 'package:sqflite/sqflite.dart';
import 'package:finsec/model/transaction_content.dart';
import 'package:finsec/utils/tables.dart';
import 'package:finsec/model/income/income_dao.dart';
import 'package:finsec/model/income/income.dart';
import 'package:finsec/model/list_item.dart';
import 'package:finsec/model/dao.dart';
import 'package:finsec/model/cardview_list_item.dart';

import 'package:finsec/utils/strings.dart';
import 'package:finsec/utils/colors.dart';
import 'package:finsec/widget/circle_icon.dart';
import 'package:finsec/data/db_provider.dart';
class DBProvider {

  static DBProvider db;    // Singleton DBProvider
  static Database _database;                // Singleton Database

  DBProvider._createInstance(); // Named constructor to create instance of DBProvider

  factory DBProvider() {

    if (db == null) {
      db = DBProvider._createInstance(); // This is executed only once, singleton object
    }
    return db;
  }

  Future<Database> get database async {

    if (_database == null) {
      _database = await initializeDatabase();
    }
    return _database;
  }

  Future<Database> initializeDatabase() async {
    // Get the directory path for both Android and iOS to store database.
    Directory directory = await getApplicationDocumentsDirectory();
    String path = directory.path + 'finsec.db';
    // Open/create the database at a given path
    var finsecDatabase = await openDatabase(path, version: 4, onCreate: _createDb, onUpgrade: _onUpgrade);
    return finsecDatabase;
  }

  void _createDb(Database db, int newVersion) async {
   // await db.execute('drop table income');
    print('CREATE THE TABLE2');
    await db.execute(incomeTable);

    //await db.execute("CREATE TABLE User(id INTEGER PRIMARY KEY, firstname TEXT, lastname TEXT, dob TEXT)");
  }

  // UPGRADE DATABASE TABLES
  void _onUpgrade(Database db, int oldVersion, int newVersion) async {
    if (oldVersion < newVersion) {
      await db.execute('drop table income');
      await db.execute(incomeTable);
    }
  }

  // Fetch Operation: Get all row objects from database
  Future<List<Map<String, dynamic>>> getTransactions(String tableName) async {
    Database db = await this.database;

   //var result = await db.rawQuery(tableName);
    var result = await db.query(tableName);
    result.forEach((row) => print(row));
   // var res = await db.insert('note', transactionType.toMap());
    return result;
  }

  // Fetch Operation: Get all row objects from database
  Future<List<Map<String, dynamic>>> getTransactionsQuery(String query) async {
    Database db = await this.database;

    var result = await db.rawQuery(query);
    return result;
  }


  // Insert Operation: Insert a transaction object to database
  Future<int> insertTransaction(String sqlQuery) async {
    Database db = await this.database;
    //var dao = new IncomeDao();
    var result = await db.rawInsert(sqlQuery); //insert(noteTable, note.toMap());
    //var result = await db.insert('noteTable', transaction);
    return result;
  }

  // Update Operation: Update a Note object and save it to database
  Future<int> updateTransaction(Map transaction) async {
    var db = await this.database;
    //var result = await db.rawUpdate(sql);// update(noteTable, note.toMap(), where: '$colId = ?', whereArgs: [note.id]);
    var result = await db.update('noteTable', transaction);
    return result;
  }

  // Delete Operation: Delete a transaction object from database
  Future<int> deleteTransaction(int id) async {
    var db = await this.database;
    int result = await db.rawDelete('DELETE FROM noteTable WHERE ');
    return result;
  }

  // Get number of Note objects in database
  Future<int> getCount() async {
    Database db = await this.database;
    List<Map<String, dynamic>> x = await db.rawQuery('SELECT COUNT (*) from noteTable');
    int result = Sqflite.firstIntValue(x);
    return result;
  }

  // Get the 'Map List' [ List<Map> ] and convert it to 'Note List' [ List<Note> ]
  Future<List<Income>> getIncomeList(String tableName) async {

    var incomeMapList = await getTransactions(tableName); // Get 'Map List' from database
    int count = incomeMapList.length;         // Count the number of map entries in db table

    List<Income> incomeList = List<Income>();
    // For loop to create a 'Income List' from a 'Map List'
    for (int i = 0; i < count; i++) {
      incomeList.add(Income.fromMap(incomeMapList[i]));
    }

    return incomeList;
  }

  // Get the 'Map List' [ List<Map> ] and convert it to 'Note List' [ List<Note> ]
  Future<List<String>> getDataList(String query) async {
    var dataMapList = await getTransactionsQuery(query); // Get 'Map List' from database
    int count = dataMapList.length;         // Count the number of map entries in db table

    List<String> dataList = List<String>();
    Map<String, dynamic> queryData;



    for (int i = 0; i < count; i++) {
      queryData = dataMapList[i];
      dataList.add(queryData["amount"]);
    }

    return dataList;
  }

}

我认为问题出在代码的以下部分

  if (amountList == null) {
      amountList = List<String>();
      updateListView();
      listItems = summaryList();
    }

updateListView()被调用,但是即使updateListView没有完成执行,代码仍继续执行到下一行。当我在summaryList()中调用amountList [0]时,出现以下错误

 RangeError (index): Invalid value: Valid value range is empty: 0
I/flutter ( 3640): 
I/flutter ( 3640): User-created ancestor of the error-causing widget was:
I/flutter ( 3640):   Column file:///C:/Users/rodrigue33/Documents/APP/finsec/lib/widget/cardview_widget.dart:45:22
I/flutter ( 3640): 
I/flutter ( 3640): When the exception was thrown, this was the stack:
I/flutter ( 3640): #0      List.[] (dart:core-patch/growable_array.dart:145:60)
I/flutter ( 3640): #1      CardviewListItemDataState.summaryList (package:finsec/data/cardview_list_item.dart:114:27)
I/flutter ( 3640): #2      CardviewListItemDataState.build (package:finsec/data/cardview_list_item.dart:80:19)
I/flutter ( 3640): #3      StatefulElement.build (package:flutter/src/widgets/framework.dart:4040:27)

这是我对正在发生的事情的假设。有人同意我吗?我如何解决在列表视图中显示数据之前等待数据库返回数据的问题?预先感谢

1 个答案:

答案 0 :(得分:1)

问题是您正在调用setState方法并更新其“ amountList”,因为setState重新加载页面时它并没有完全执行“ listItems = summaryList();”。

也许一个快速的解决方法是创建一个布尔检查并将其保留为false,在执行setState时将其设置为true,并在您的构建器方法中执行以下操作:

if (amountList == null) {
  amountList = List<String>();
  updateListView();
}
 if(check){ 
   listItems = summaryList();
 }

注意:我建议在您的方法中使用async和await,而不要在将来使用。

void updateListView() async{

  final Database db = await db.initializeDatabase();
  List<String> incomeList = await db.getDataList(test);
  setState(() {
    this.amountList = amountList;
    this.count = this.amountList.length;
    this.check = true;
  });


}

希望我能帮助您!