web-dev-qa-db-ja.com

Flutter:タイプ 'Future <dynamic>'はタイプ 'Widget'のサブタイプではありません

Flutterアプリにデータを保存するためにsqliteを使用しています。フィルターチップで開くモーダルボトムシートがあり、フィルターチップを選択すると、データベースにアイテムが追加されます。アイテムがすでに存在する場合、フィルターチップがチェックされます。データベース関数を呼び出してアイテムがすでに存在するかどうかを確認すると、次のエラーが発生します。

Asyncとawaitの両方を使用してみました。

データベースクエリコード:

// FIND TAG
findTag(int tagId) async {
    var dbConnection = await db;
    var res = await  dbConnection.query("$TABLE_NAME", where: "tagId = ?", whereArgs: [tagId]);
    return res.isNotEmpty ? true : false ;
  }

モーダルボトムシートウィジェットコンテナコード:

Widget build(BuildContext context) {
    setState(() {
      _index = widget.index;
      _list =widget.list;
    });

    return new Container(
      padding: new EdgeInsets.all(27.0),
      child: new Column(
        mainAxisAlignment: MainAxisAlignment.start,
        mainAxisSize: MainAxisSize.min,              
        crossAxisAlignment: CrossAxisAlignment.start,
        children: <Widget> [
          new Text(_list[_index]["title"], style: new TextStyle(  fontWeight: FontWeight.bold, fontSize: 22),),          
          new Text(_list[_index]["description"]),
          getFilterChipsWidgets(),
        ],
      ),
    );

}


getFilterChipsWidgets()
  async {

    List<Widget> tagsList = new List<Widget>();
      for(var i=0; i<_list[_index]["tags"].length; i++) {       
        var dbHelper = DBHelper();
        int id = int.parse(_list[_index]["tags"][i]["id"]);

        var exist = await dbHelper.findTag(id);
        FilterChip item = new FilterChip(
          label: Text(_list[_index]["tags"][i]["name"].toString(),), 
          selected: exist,
          onSelected: (bool newValue) {
            if(newValue) {
              dbHelper.addNewTag(id);
            } else {
              dbHelper.deleteNewTag(id);
            }
          },
        );
        tagsList.add(item);       
      }

       return Wrap(
          spacing: 8.0, // gap between adjacent chips
          runSpacing: 4.0, // gap between lines
          children: tagsList,
        );
}


2
Niru

GetFilterChipsWidgets()は非同期関数であるため、Futureを返します。将来を待ち、ウィジェットを保存して、完了したらsetStateを一覧表示して呼び出すことができます。または、次のようにFutureBuilderでラップします。

    children: <Widget> [
      new Text(_list[_index]["title"], style: new TextStyle(fontWeight: FontWeight.bold, fontSize: 22),),          
      new Text(_list[_index]["description"]),
      FutureBuilder<Widget>(
       future: getFilterChipsWidgets,
       builder: (BuildContext context, AsyncSnapshot<Widget> snapshot){
         if(snapshot.hasData)
           return snapshot.data;

         return Container(child: CircularProgressIndicator());
       }
      ),
    ],
7
knezzz

誤って関数asyncを割り当て、関数ブロック内でawaitプロセスを使用している場所がないことも時々見られます。

同様のシナリオがすでに発生しており、この未使用のasyncを関数から削除することで、上記の問題を解決しました。

関数をasyncにすると、関数リクエスターはそれをFuture<T>の方法で処理するので、注意してください。

1
ArifMustafa