[英]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.