簡體   English   中英

sqflite 和 Flutter:在第二個屏幕上顯示數據

[英]sqflite and Flutter: display data on a second screen

我試圖了解使用 sqflite package 的數據庫的原理。

我測試了 web 上的教程,該教程適用於文本字段和結果顯示。

當我測試相同的代碼但適合 2 個屏幕時,它僅在我在 Android Studio 中進行熱加載時才有效,我無法弄清楚問題出在哪里。

有人可以向我解釋我不明白什么來解決問題嗎?

謝謝

我的主頁:我的主頁.dart

import 'package:flutter/material.dart';
import 'package:test_sqflite_v3/DatabaseHelper.dart';
import 'package:test_sqflite_v3/todo.dart';

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key}) : super(key: key);


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

class _MyHomePageState extends State<MyHomePage> {
  TextEditingController textController = new TextEditingController();

  List<Todo> taskList = List();

  @override
  void initState() {
    super.initState();

    DatabaseHelper.instance.queryAllRows().then((value) {
      setState(() {
        value.forEach((element) {
          taskList.add(Todo(id: element['id'], title: element["title"]));
        });
      });
    }).catchError((error) {
      print(error);
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Home'),
      ),
      body: Padding(
        padding: const EdgeInsets.all(40.0),
        child: Column(
          mainAxisAlignment: MainAxisAlignment.spaceAround,
          children: <Widget>[
            TextFormField(
              decoration: InputDecoration(hintText: "Enter a task"),
              controller: textController,
            ),

            FlatButton(
                child: Text('add B2D'),
              onPressed: () {
                _addToDB();
                  Navigator.pushNamed(context, '/controller1');
                textController.clear();
              },
            )
          ],
        ),
      ),
    );
  }

  void _addToDB() async {
    String task = textController.text;
    var id = await DatabaseHelper.instance.insert(Todo(title: task));
    setState(() {
      taskList.insert(0, Todo(id: id, title: task));
    });
  }
 }

我的第二個屏幕詳細信息:controller1.dart

import 'package:flutter/material.dart';
import 'package:test_sqflite_v3/DatabaseHelper.dart';
import 'package:test_sqflite_v3/todo.dart';

class Controller1 extends StatefulWidget {
  Controller1({Key key}) : super(key: key);


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

class _Controller1State extends State<Controller1> {

  List<Todo> taskList = List();

  @override
  void initState() {
    super.initState();

    DatabaseHelper.instance.queryAllRows().then((value) {
      setState(() {
        value.forEach((element) {
          taskList.add(Todo(id: element['id'], title: element["title"]));
        });
      });
    }).catchError((error) {
      print(error);
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Controller1'),
      ),
      body: taskList.isEmpty
          ? Center(child: Text('No Data !!!'),)
          : ListView.builder(
          //itemCount: taskList.length,
          itemBuilder: (context, index) {

        if (index == taskList.length) return null;
        return ListTile(
          title: Text(taskList[index].title),
          leading: Text(taskList[index].id.toString()),
          trailing: IconButton(
            icon: Icon(Icons.delete),
            onPressed: () => _deleteTask(taskList[index].id),
          ),
        );
      }),
    );
  }

  void _deleteTask(int id) async {
    await DatabaseHelper.instance.delete(id);
    setState(() {
      taskList.removeWhere((element) => element.id == id);
    });
  }
}

我的數據庫:

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

class DatabaseHelper {
  static final _databaseName = "todo.db";
  static final _databaseVersion = 1;

  static final table = 'todo';

  static final columnId = 'id';
  static final columnTitle = 'title';

  DatabaseHelper._privateConstructor();
  static final DatabaseHelper instance = DatabaseHelper._privateConstructor();

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

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

  // SQL code to create the database table
  Future _onCreate(Database db, int version) async {
    await db.execute('''
          CREATE TABLE $table (
            $columnId INTEGER PRIMARY KEY AUTOINCREMENT,
            $columnTitle STRING NOT NULL
          )
          ''');
  }

  Future<int> insert(Todo todo) async {
    Database db = await instance.database;
    var res = await db.insert(table, todo.toMap());
    return res;
  }

  Future<List<Map<String, dynamic>>> queryAllRows() async {
    Database db = await instance.database;
    var res = await db.query(table, orderBy: "$columnId DESC");
    return res;
  }

  Future<int> delete(int id) async {
    Database db = await instance.database;
    return await db.delete(table, where: '$columnId = ?', whereArgs: [id]);
  }

  Future<void> clearTable() async {
    Database db = await instance.database;
    return await db.rawQuery("DELETE FROM $table");
  }
}

我的列表:

    class Todo {
  int id;
  String title;

  Todo({this.id, this.title});

  Map<String, dynamic> toMap() {
    return {'id': id, 'title': title};
  }
}

當我看到你的代碼時,也許你的initState()有問題

  @override
  void initState() {
    super.initState();

    DatabaseHelper.instance.queryAllRows().then((value) {

        value.forEach((element) {
          taskListTemp.add(Todo(id: element['id'], title: element["title"]));
        });

      setState(() {
        taskList = taskListTemp;
      });
    }).catchError((error) {
      print(error);
    });
  }

您在 forEach 中使用setState這是我認為的主要問題。

我找到了一個教程,可以讓我回答我的問題; 這是代碼:

DatabaseHelpert.dart

    import ...;


class DatabaseHelper {
  //Create a private constructor
  DatabaseHelper._();

  static const databaseName = 'todos_database.db';
  static final DatabaseHelper instance = DatabaseHelper._();
  static Database _database;
  static final columnId = 'id';

  Future<Database> get database async {
    if (_database == null) {
      return await initializeDatabase();
    }
    return _database;
  }

  initializeDatabase() async {
    return await openDatabase(join(await getDatabasesPath(), databaseName),
        version: 1, onCreate: (Database db, int version) async {
      await db.execute(
          "CREATE TABLE todos(id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, title TEXT, content TEXT)");
    });
  }

  insertTodo(Todo todo) async {
    final db = await database;
    var res = await db.insert(Todo.TABLENAME, todo.toMap(),
        conflictAlgorithm: ConflictAlgorithm.replace);
    return res;
  }

  Future<List<Todo>> retrieveTodos() async {
    final db = await database;
    final List<Map<String, dynamic>> maps = await db.query(Todo.TABLENAME, orderBy: "$columnId DESC");

    return List.generate(maps.length, (i) {
      return Todo(
        id: maps[i]['id'],
        title: maps[i]['title'],
        content: maps[i]['content'],
      );
    });
  }

  updateTodo(Todo todo) async {
    final db = await database;

    await db.update(Todo.TABLENAME, todo.toMap(),
        where: 'id = ?',
        whereArgs: [todo.id],
        conflictAlgorithm: ConflictAlgorithm.replace);
  }

  deleteTodo(int id) async {
    var db = await database;
    db.delete(Todo.TABLENAME, where: 'id = ?', whereArgs: [id]);
  }
}

Todo.dart:

class Todo {
  final int id;
  final String content;
  final String title;
  static const String TABLENAME = "todos";

  Todo({this.id, this.content, this.title});

  Map<String, dynamic> toMap() {
    return {'id': id, 'content': content, 'title': title};
  }
}

主.dart:

import ...;
  

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      title: 'Your favorite todo app',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: Home(),
    );
  }
}

主頁.dart:

import ...;
  

class Home extends StatefulWidget {
  final Todo todo;

  const Home({Key key, this.todo}) : super(key: key);

  @override
  State<StatefulWidget> createState() => _HomeState(todo);

}

class _HomeState extends State<Home> {



  Todo todo;
  final titleTextController = TextEditingController();
  final descriptionTextController = TextEditingController();

  _HomeState(this.todo);

  @override
  void initState() {
    super.initState();
    if (todo != null) {
      descriptionTextController.text = todo.content;
      titleTextController.text = todo.title;
    }
  }

  @override
  void dispose() {
    super.dispose();
    descriptionTextController.dispose();
    titleTextController.dispose();
  }

  @override
  Widget build(BuildContext context) {


    return Scaffold(
      appBar: AppBar(
        title: Text('Page TextField'),
      ),
      body: GestureDetector(
        onTap: () {
          FocusScopeNode currentFocus = FocusScope.of(context);
          if (!currentFocus.hasPrimaryFocus && currentFocus.focusedChild != null) {
            currentFocus.focusedChild.unfocus();
          }
        },
        child: SingleChildScrollView(
          child: Padding(
            padding: const EdgeInsets.all(20.0),
            child: Column(
              children: <Widget>[
                TextField(
                  decoration: InputDecoration(
                      border: OutlineInputBorder(),
                      labelText: "Title"),
                  maxLines: 1,
                  controller: titleTextController,
                ),
                Container(
                  height: 40.0,
                ),
                TextField(
                    decoration: InputDecoration(
                        border: OutlineInputBorder(),
                        labelText: "Description"),
                    maxLines: 5,
                    controller: descriptionTextController,
                  ),

                Container(
                  height: 40.0,
                ),
                RaisedButton(
                    child: Text("enregistrer données à la BDD"),
                    onPressed: () {
                      _saveTodo(titleTextController.text, descriptionTextController.text);
                      titleTextController.clear();
                      descriptionTextController.clear();
                    }
                ),
                Container(
                  height: 40.0,
                ),
                RaisedButton(
                  onPressed: () {
                    Navigator.push(context,
                      MaterialPageRoute(builder: (context) => Detail()),
                    );
                  },
                  child: Text("accès screen détail"),
                ),
              ],
            ),
          ),
        ),
      ),
    );
  }

  _saveTodo(String title, String content) async {
    if (todo == null) {
      DatabaseHelper.instance.insertTodo(Todo(
          title: titleTextController.text,
          content: descriptionTextController.text));
    } else {
      await DatabaseHelper.instance
          .updateTodo(Todo(id: todo.id, title: title, content: content));
    }
  }
}

詳情dart:

import ...;

class  Detail extends StatefulWidget {
  @override
  _DetailState createState() => _DetailState();
}

class _DetailState extends State<Detail> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Détail'),
      ),
      body: FutureBuilder<List<Todo>>(
        future: DatabaseHelper.instance.retrieveTodos(),
        builder: (context, snapshot) {
          if (snapshot.hasData) {
            return ListView.builder(
              itemCount: snapshot.data.length,
              itemBuilder: (BuildContext context, int index) {
                return ListTile(
                  title: Text(snapshot.data[index].title),
                  leading: Text(snapshot.data[index].id.toString()),
                  subtitle: Text(snapshot.data[index].content),
                  trailing: IconButton(
                      alignment: Alignment.center,
                      icon: Icon(Icons.delete),
                      onPressed: () async {
                        _deleteTodo(snapshot.data[index]);
                        setState(() {});
                      }),
                );
              },
            );
          } else if (snapshot.hasError) {
            return Text("Oops!");
          }
          return Center(child: CircularProgressIndicator());
        },
      ),
    );
  }
  _deleteTodo(Todo todo) {
    DatabaseHelper.instance.deleteTodo(todo.id);
  }
}

不要忘記更新您的導入'...'; 和您的 pubspec.yaml 文件(路徑和 sqflite -> Pub 獲取)...

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM