【问题标题】:Flutter, future builder and snapshot.data, the data never gets loadedFlutter,future builder和snapshot.data,数据永远不会被加载
【发布时间】:2020-08-02 19:26:58
【问题描述】:

我正在尝试构建一个非常简单的应用笔记并使用 SQFlite 包将笔记保存到本地数据库。在我的代码中,我使用未来的构建来显示 CircularProgressIndicator,同时从数据库加载数据,而 db 目前是空的,因此应用程序应该显示一个空的主体。我的问题是数据永远不会被加载并且循环进度指示器是无限的。此外,“添加注释”按钮会打开一个警报对话框,其中包含两个文本字段,它们应该获取文本,将其从数据库中插入到表中,并且文本应该显示在正文中的卡片中,但这不会发生。 我的代码:

main.dart

import 'package:flutter/material.dart';

import 'home_screen.dart';
import 'note_inherited_widget.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return NoteInheritedWidget(
          MaterialApp(
        home: HomeScreen(),
        theme: ThemeData(
            primaryColor: Colors.deepOrange, accentColor: Colors.deepPurple),
      ),
    );
  }
}

home_screen.dart

import 'package:flutter/material.dart';

import 'package:simple_notes/note_inherited_widget.dart';
import 'package:simple_notes/providers/note_providers.dart';
import './note_inherited_widget.dart';

class HomeScreen extends StatefulWidget {
  @override
  _HomeScreenState createState() => _HomeScreenState();
}

class _HomeScreenState extends State<HomeScreen> {
  final TextEditingController titleController = TextEditingController();
  final TextEditingController textController = TextEditingController();

  @override
  void dispose() {
    // Clean up the controller when the widget is disposed.
    titleController.dispose();
    textController.dispose();
    super.dispose();
  }

  DummyDataProvider notes;

  @override
  void didChangeDependencies() {
    super.didChangeDependencies();
    notes = NoteInheritedWidget.of(context);
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          title: Text('Simple Notes'),
          centerTitle: true,
        ),
        body: FutureBuilder(
            future: NoteProvider.getNoteList(),
            builder: (context, snapshot) {
              if (snapshot.connectionState == ConnectionState.done) {
                final notes = snapshot.data;
                ListView.builder(
                  itemBuilder: (context, index) {
                    return Card(
                      child: Column(
                        children: <Widget>[
                          NoteTitle(notes[index]['title']),
                          NoteText(notes[index]['text'])
                        ],
                      ),
                    );
                  },
                  itemCount: notes.length,
                );
              }
              return Center(child: CircularProgressIndicator());
            }
            ),
        bottomNavigationBar: (FlatButton(
            onPressed: () {
              showMyDialog(context);
            },
            child: Text('Add note'))));
  }

  Future<void> showMyDialog(
    BuildContext context,
  ) {
    return showDialog<void>(
        context: context,
        builder: (BuildContext context) {
          return AlertDialog(
            content: Column(
              children: <Widget>[
                TextField(
                  controller: titleController,
                ),
                TextField(
                  controller: textController,
                )
              ],
            ),
            actions: <Widget>[
              MaterialButton(onPressed: () {
                final title = titleController.text;
                final text = textController.text;
                NoteProvider.insertNote({
                  'title': title,
                  'text': text
                });
                Navigator.pop(context);
              }, 
              child: Text('save')
              )
            ],
          );
        });
  }
}

class NoteTitle extends StatelessWidget {
  final String title;

  NoteTitle(this.title);

  @override
  Widget build(BuildContext context) {
    return Text(
      title,
      style: TextStyle(fontSize: 25, fontWeight: FontWeight.bold),
    );
  }
}

class NoteText extends StatelessWidget {
  final String text;

  NoteText(this.text);

  @override
  Widget build(BuildContext context) {
    return Text(
      text,
      style: TextStyle(
        color: Colors.grey.shade600,
      ),
      maxLines: 2,
      overflow: TextOverflow.ellipsis,
    );
  }
}

class SaveButton extends StatelessWidget {
  final Function onPressed;

  SaveButton(this.onPressed);

  @override
  Widget build(BuildContext context) {
    return MaterialButton(
      onPressed: () {

        Navigator.pop(context);
      },
      child: Text('Save'),
    );
  }
}

note_providers.dart

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

class NoteProvider {
  static Database db;

  static Future open() async {
    db = await openDatabase(join(await getDatabasesPath(), 'notes.db'),
    version: 1,
    onCreate: (Database db, int version) async {
      db.execute('''
      CREATE TABLE notes(
        id INTEGER PRIMARY KEY AUTOINCREMENT,
        title TEXT NOT NULL,
        text TEXT NOT NULL
      );
      ''');
     }
    );
  }

  static Future<List<Map<String, dynamic>>> getNoteList() async {
      if (db == null) {
        await open();
      }
      return await db.query('Notes');
    }

    static Future insertNote (Map<String, dynamic> note) async {
      await db.insert('Notes', note);
    }
}

如果你能解释为什么会发生这种情况,那就太好了。由于我还在学习 Flutter,因此我无法查明问题所在。

提前致谢。

【问题讨论】:

    标签: flutter dart


    【解决方案1】:

    您似乎在ListView.builder 附近缺少return

    return ListView.builder(
    

    因为目前它总是返回循环进度指示器,即使 Future 完成。

    【讨论】:

    • 非常正确,它有效。非常感谢你的回答。现在我的另一个问题是,当我使用“添加按钮”时,确实会添加标题和文本,但只有在我重新启动应用程序后它们才会显示在正文中。你能给我指出如何开始解决这个问题的方向吗?提前致谢。
    • 您需要再次运行查询。您可以尝试调用 SetState(() {}) 来查看它是否会再次触发未来的构建器。
    猜你喜欢
    • 2020-07-17
    • 2021-03-02
    • 2014-10-19
    • 1970-01-01
    • 2021-06-17
    • 1970-01-01
    • 2021-03-04
    • 2019-10-26
    • 2015-04-25
    相关资源
    最近更新 更多