Flutter:SQLite的“收藏夹”功能-首次加载时出现问题

时间:2020-06-02 22:54:49

标签: sqlite flutter dart sqflite

我已经创建了一个详细信息页面,并使用了Medium文章中的示例。我能够成功执行CRUD操作。

当我加载DetailsPage时,我想检查表是否具有ID,如果是,则将收藏夹图标设为黄色。

class _DetailPageState extends State<DetailPage> {
  bool isFav = false;
  MyImpData myData;
  _DetailPageState(this.myData);

  // reference to our single class that manages the database
  final dbHelper = DatabaseHelper.instance;

  @override
  Widget build(BuildContext context) {
    Widget heading = new Container(...),);

    Widget middleSection = new Expanded(...);

    Widget bottomBanner = new Container(...),);

    Widget body = new Column(...);

    final makeBottom = Container(
      height: 55.0,
      child: BottomAppBar(
        color: Color.fromRGBO(58, 66, 86, 1.0),
        child: Row(
          mainAxisAlignment: MainAxisAlignment.spaceEvenly,
          children: <Widget>[
            IconButton(
              icon: buildIcon(),
              onPressed: () {
                _insertOrDelete(myData.id);
              },
            ),
            IconButton(
              icon: Icon(Icons.share, color: Colors.white),
              onPressed: () => share(context, myData),
            )
          ],
        ),
      ),
    );

    return Scaffold(
      appBar: AppBar(...),
      body: Container(...),
      bottomNavigationBar: makeBottom,
    );
  }

  Icon buildIcon() {
    if (isFav) {
      return Icon(Icons.favorite, color: Colors.yellow);
    } else {
      return Icon(Icons.favorite_border, color: Colors.white);
    }
  }

  void share(BuildContext context, MyImpData myData) {...}

  void _insert() async {
    // row to insert
    Map<String, dynamic> row = {
      DatabaseHelper.columnName: myData.name,
      DatabaseHelper.columnDesc: myData.desc,
      DatabaseHelper.columnLoc: myData.location,
      DatabaseHelper.columnId: myData.id
    };
    final id = await dbHelper.insert(row);
    print('inserted row id: $id');
  }

  void _checkFav(String checkId) async {
    final rowsPresent = await dbHelper.queryForFav(checkId);
    if (rowsPresent > 0) {
      print('success');
      isFav = true;
    } else {
      print('Nothing found so inserting you dodo');
      isFav = false;
      //_insert();
    }
    //rowsPresent.forEach((row) => print(row));
  }

  void _insertOrDelete(String id) async {
    final rowsPresent = await dbHelper.queryForFav(id);
    if (rowsPresent > 0) {
      print('Its favourite and removing it');
      _delete();
      isFav = false;
    } else {
      print('Nothing found so inserting you dodo');
      _insert();
      isFav = true;
    }
  }

  void _delete() async {...}
}

DBHelper.dart文件的queryForFav(id)具有以下内容

//Raw query to check if it is in the favourites
  Future<int> queryForFav(String checkId) async {
    Database db = await instance.database;
    int noOfRows = 0;
    try {
      noOfRows = Sqflite.firstIntValue(await db.rawQuery(
          'SELECT COUNT(*) FROM $table WHERE $columnId = ?',
          ['$checkId']));
    } catch (e) {
      print(e);
    }
    return noOfRows;
  }

我的尝试是创建一个标志isFav并在检查数据库时进行设置。但是,这总是错误的,因为没有执行查询。只有当我按下按钮时,才会执行实际的数据库查询。 任何帮助,将不胜感激。

1 个答案:

答案 0 :(得分:0)

更改此类的IconButton(child,buildIcon(),...)

class FavIconWidget extends StatefulWidget {
  final MyImpData myData;

  FavIconWidget(this.myData);

  @override
  _FavIconWidgetState createState() => _FavIconWidgetState();
}

class _FavIconWidgetState extends State<FavIconWidget> {
  final dbHelper = DatabaseHelper.instance;

  Future<bool> get isFav async {
    final rowsPresent = await dbHelper.queryForFav(widget.myData.id);
    if (rowsPresent > 0) {
      print('Its favourite and removing it');
      await _delete();
      return false;
    } else {
      print('Nothing found so inserting you dodo');
      await _insert();
      return true;
    }
  }

  void _insert() async {

    // row to insert
    Map<String, dynamic> row = {
      DatabaseHelper.columnName: widget.myData.name,
      DatabaseHelper.columnDesc: widget.myData.desc,
      DatabaseHelper.columnLoc: widget.myData.location,
      DatabaseHelper.columnId: widget.myData.id
    };
    final id = await dbHelper.insert(row);
    print('inserted row id: $id');
  }


  void _delete() async {}

  @override
  Widget build(BuildContext context) {
    return FutureBuilder<bool>(
        future: isFav,
        initialData: false,// you can define an initial value while the db returns the real value
        builder: (context, snapshot) {
          if(snapshot.hasError) return const Icon(Icons.error, color: Colors.red); //just in case the db return an error
          return IconButton(
            icon: snapshot.data ? const Icon(Icons.favorite, color: Colors.yellow) : 
             Icon(Icons.favorite, color: Colors.white),
            onPressed: () => setState(() {})
          );
        });
  }

}

基本上,它用FutureBuilder包装图标,这是一个特殊的小部件,等待一个未来值(在这种情况下,返回数据库行),您可以在等待时为其提供初始值(在这种情况下,我给它一个false),但您可以忽略它,并使用snapshot.hasData检查是否有一个值,然后返回CircularProgressIndicator来告诉用户您正在获取数据

return FutureBuilder<bool>(
        future: isFav,
        initialData: false,// you can define an initial value while the db returns the real value
        builder: (context, snapshot) {
          if(snapshot.hasError) return const Icon(Icons.error, color: Colors.red); //just in case the db return an error
          if(snapshot.hasData)
          return IconButton(
            icon: snapshot.data ? const Icon(Icons.favorite, color: Colors.yellow) : 
             Icon(Icons.favorite, color: Colors.white),
            onPressed: () => setState(() {})
          );

          return CircularProgressIndicator(); //if there is no initial value and the future is not yet complete
        });

我制作了这个StatefulWidget,所以当您按下按钮setState并重新运行isFav future来再次检查数据库时(但它只是重新构建了此iconbutton,而不是整个页面)。如果您要根据isFav值而不是仅根据图标来更新整个页面,则必须在该Scaffold的正文中或至少在您确实需要检查该值的小部件树中使用该FutureBuilder。