【问题标题】:Flutter FutureBuilder not building with data from sqliteFlutter FutureBuilder 不使用来自 sqlite 的数据构建
【发布时间】:2020-05-29 09:19:06
【问题描述】:

我是 Flutter 的新手,正在尝试编写能够从 sqlite 中获取价值的应用程序。根据我的尝试,它需要使用 FutureBuilder 小部件。

但是我写的以下代码,FutureBuilder 小部件似乎从 sqlite 获取数据,但从未调用过“builder”属性:

import 'package:flutter/material.dart';
import 'package:flutter_spinkit/flutter_spinkit.dart';
import 'package:flutterapp/dbHelper.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      routes:{
        "/": (context) =>Test()
      }
    );
  }
}

class Test extends StatefulWidget {
  @override
  _TestState createState() => _TestState();
}

class _TestState extends State<Test> {

  bool nameCheck = false; // Use to check name textfield has correctly be inputed
  TextEditingController nameController = TextEditingController();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        body:Column(
          children: <Widget>[
            SizedBox(height:300),
            Row(
              children: <Widget>[
                Expanded(
                    child: TextField(
                      controller: nameController,
                    )
                ),
                IconButton(
                  icon: Icon(Icons.check_circle),
                    onPressed:(){
                      return FutureBuilder(
                          future: getData(nameController.text),
                          builder: (BuildContext context, AsyncSnapshot<List<Map>>snapshot) {
                            print("Start future"); // never get printed
                            List<Widget> children;
                            if (snapshot.hasData) {
                              children = <Widget>[
                                Builder(
                                    builder: (BuildContext context) {
                                      print("got data");
                                      final result = snapshot.data;
                                      print(result) ; // never get printed
                                      setState(() {
                                        nameCheck = true;
                                      });
                                      return Container();
                                    })
                              ];
                            } else {
                              children = <Widget>[
                                AlertDialog(
                                    content: SpinKitCircle(
                                      color: Colors.white,
                                      size: 80.0,
                                    ))
                              ];
                            }
                            return Center(
                                child: Container(
                                    color: Colors.blue,
                                    child: Column(
                                      mainAxisAlignment:
                                      MainAxisAlignment
                                          .center,
                                      crossAxisAlignment:
                                      CrossAxisAlignment
                                          .center,
                                      children: children,
                                    )));
                          });}
                )
              ],
            ),
            Builder(
              builder: (BuildContext context){
                if (nameCheck == true){
                  return Text("test");
                }
                return Container();
              }
            )
          ],
        )
    );
  }
}

Future<List<Map>> getData(String input_name) async{
  final dbHelper = DBHelper.instance;
  await dbHelper.database;
  final result = await dbHelper.query("SELECT * FROM Guest WHERE Name = \"$input_name\"");
  print(result); // This get printed
  return result;
}

DBHelper代码如下,基本上就是建立了一个sqlite数据库和一些数据库操作:

import 'package:sqflite/sqflite.dart';
import 'package:path/path.dart';
import 'dart:io';
import 'package:path_provider/path_provider.dart';

class DBHelper {
  static final _databaseName = "MonetaryDB.db";
  static final _databaseVersion = 1;

  static final create_table_Test = "CREATE TABLE \"Guest\" (\"Name\"    TEXT NOT NULL PRIMARY KEY, \"Money\" INTEGER, \"Person\" INTEGER)";

  static final String insert_guest = "INSERT INTO Guest (Name, Money, Person) VALUES (\"testname\", 1000, 1)";

  DBHelper._privateConstructor();

  static final DBHelper instance = DBHelper._privateConstructor();

  static Database _database;
  Future<Database> get database async {
    if (_database != null) {
      return _database;}
    else{
      _database = await _initDatabase();
    return _database;}
  }

  _initDatabase() async {
    Directory documentsDirectory = await getApplicationDocumentsDirectory();
    String path = join(documentsDirectory.path, _databaseName);
    return await openDatabase(path,
      version: _databaseVersion,
      onCreate: _onCreate,
    );
  }

  Future _onCreate(Database db, int version) async {
    await db.execute(create_table_Test);
    await db.rawInsert(insert_guest);
  }

  Future<int> insert(String statement) async {
    Database db = await instance.database;
    return await db.rawInsert(statement);
  }

  Future<List<Map>> query(String statement) async {
    Database db = await instance.database;
    return await db.rawQuery(statement);
  }

  Future<int> update(String statement) async{
    Database db = await instance.database;
    return await db.rawUpdate(statement);
  }

  Future<int> delete(String statement) async{
    Database db = await instance.database;
    return db.rawDelete(statement);
  }
}

如果我只是将 IconButton onPressed 函数更改为 setState((){nameCheck = true}),则 Text("test") 小部件将显示,所以问题一定是 FutureBuilder。另外,getData() 函数可以从 sqlite 数据库中得到正确的结果

我不知道为什么 FutureBuilder 没有构建,有人知道吗? 谢谢!

【问题讨论】:

  • 你有什么异常吗?
  • 你为什么首先在 onTap 中使用FutureBuilder
  • @jitsm555 我没有得到任何异常。
  • @Adnan karim 嗯...我不太确定。我想要做的是当我按下按钮时,它将使用 TextEditingController() 中的值来搜索数据库中的值以获得结果。然后它将使用结果做其他工作。所以我们不能直接在onPressed(){}函数中放置“FutureBuilder”吗?
  • FutureBuilder 是一个Widget,它是在从Future 方法获取数据后构建的。

标签: sqlite flutter dart flutter-layout


【解决方案1】:

因此,在评论部分的帮助下,我更改了代码并成功了:

...
  Widget build(BuildContext context) {
    return Scaffold(
        body:Column(
          children: <Widget>[
            SizedBox(height:300),
            Row(
              children: <Widget>[
                Expanded(
                    child: TextField(
                      controller: nameController,
                    )
                ),
                IconButton(
                  icon: Icon(Icons.check_circle),
                    onPressed:(){
                    return showDialog(
                      context: context,
                      builder: (BuildContext context){
                        return AlertDialog(
                          actions: <Widget>[
                            SizedBox(
                              width: 300,
                              height: 300,
                              child: FutureBuilder(
                                  future: getData(nameController.text),
                                  builder: (BuildContext context, AsyncSnapshot<List<Map>>snapshot) {
                                    if (snapshot.hasData) {
                                      final result = snapshot.data;
                                      SchedulerBinding.instance.addPostFrameCallback((_) => setState(() {
                                        nameCheck = true;
                                      }));
                                      Navigator.pop(context, true);
                                    }
                                    else {
                                      return Container(
                                          child: SpinKitCircle(
                                            color: Colors.white,
                                            size: 80.0,
                                          ));
                                    }
                                    return Container(color: Colors.blue);
                                  })
                            ),
                          ],
                        );
                      }
                    );
                  }
                )
              ],
            ),
            Builder(
              builder: (BuildContext context){
                if (nameCheck == true){
                  return Text("test");
                }
                return Container();
              }
            )
          ],
        )
    );
  }
...

其他代码还是一样的。

就像上面的评论部分所建议的那样,主要问题是没有地方可以为将要构建的 FutureBuilder 小部件构建。为了解决这个问题,我将 FutureBuilder 小部件放入 AlertDialog 小部件中,因为我仍然希望在加载时保留 SpinKitCircle 小部件。

我也放弃了 FutureBuilder 小部件末尾的 Column 小部件,并删除了 FutureBuilder 小部件开头的 Builder 小部件,在没有 Column 时不再需要它。

上述代码仍然抛出一个可接受的异常:“setState() or markNeedsBuild() 在构建期间调用。”但是整个事情仍然可以运行,所以我会尝试改天。

感谢评论区的建议。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-08-01
    • 2019-11-10
    • 2020-06-16
    • 2018-12-24
    • 2021-01-18
    • 1970-01-01
    相关资源
    最近更新 更多