我似乎无法更新或编辑我的Todo应用程序



我的客户应用程序(您将客户详细信息添加到列表中)成功地向数据库添加和删除数据,并正确设置状态。但是我不能让我的编辑/更新功能工作。

当我单击编辑图标时,它成功地显示了现有数据的详细信息,但是当我更改详细信息(文本)时,它不会更新以使用新数据设置状态。

函数insertTodo,deleteTodoupdateTodo是问题:

图书馆

import 'package:sqflite/sqflite.dart';
import 'package:path/path.dart';
class Todo {
int? id;
final String title;
final String name;
final String phone;
final String fax;
final String email;
final String street;
final String city;
final String town;
final String code;
bool isExpanded;
Todo({
this.id,
required this.title,
required this.name,
required this.phone,
required this.fax,
required this.email,
required this.street,
required this.city,
required this.town,
required this.code,
this.isExpanded = false,
});
Map<String, dynamic> toMap() {
return {
'id': id,
'title': title,
'name': name,
'phone': phone,
'fax': fax,
'email': email,
'street': street,
'city': city,
'town': town,
'code': code,
'isExpanded': isExpanded ? 1 : 0,
};
}

@override
String toString() {
return 'Todo(id : $id, title : $title, name : $name, phone : $phone, fax: $fax, email: 
$email, street: $street, city: $city, town: $town, code: $code, isExpanded : 
$isExpanded,)';
}
}
class DatabaseConnect {
Database? _database;
Future<Database> get database async {
final dbpath = await getDatabasesPath();
const dbname = 'todo.db';
final path = join(dbpath, dbname);
_database = await openDatabase(path, version: 1, onCreate: _createDB);
return _database!;
}
Future<void> _createDB(Database db, int version) async {
await db.execute('''
CREATE TABLE todo(
id INTEGER PRIMARY KEY AUTOINCREMENT,
title TEXT,
name TEXT,
phone TEXT,
fax TEXT,
email TEXT,
street TEXT,
city TEXT,
town TEXT,
code TEXT,
isExpanded INTEGER

)
''');
}
Future<void> insertTodo(Todo todo) async {
final db = await database;
await db.insert(
'todo',
todo.toMap(),
conflictAlgorithm: ConflictAlgorithm.replace,
);
}
Future<void> deleteTodo(Todo todo) async {
final db = await database;
await db.delete(
'todo',
where: 'id == ?',
whereArgs: [todo.id],
);
}
Future<void> updateTodo(Todo todo) async {
final db = await database;
await db.update(
'todo',
todo.toMap(),
where: 'id = ?',
whereArgs: [todo.id],
);
}
Future<List<Todo>> getTodo() async {
final db = await database;
List<Map<String, dynamic>> items = await db.query(
'todo',
orderBy: 'title ASC',
); 
return List.generate(
items.length,
(i) => Todo(
id: items[i]['id'],
title: items[i]['title'],
name: items[i]['name'],
phone: items[i]['phone'],
fax: items[i]['fax'],
email: items[i]['email'],
street: items[i]['street'],
city: items[i]['city'],
town: items[i]['town'],
code: items[i]['code'],
isExpanded: items[i]['isExpanded'] == 1 ? true : false,
),
);
}
Future<List<Todo>> searchContacts(String keyword) async {
final db = await database;
List<Map<String, dynamic>> items =
await db.query('todo', where: 'title LIKE ?', whereArgs: ['$keyword%']);
return List.generate(
items.length,
(i) => Todo(
id: items[i]['id'],
title: items[i]['title'],
name: items[i]['name'],
phone: items[i]['phone'],
fax: items[i]['fax'],
email: items[i]['email'],
street: items[i]['street'],
city: items[i]['city'],
town: items[i]['town'],
code: items[i]['code'],
isExpanded: items[i]['isExpanded'] == 1 ? true : false,
),
);
}
}

下面是我的客户页面,其中函数addItem,deleteItem,updateItem被称为链接到数据库的页面,也是我setState的页面(应用程序在采取任何行动后返回的主机)。它描绘了添加新客户详细信息、删除现有详细信息和更新新信息后的数据列表:

客户

import 'package:flutter/material.dart';
import 'package:flutter/cupertino.dart';
import '../customerlist.dart';
import '../library.dart';
import '../user_input.dart';
class Customer extends StatefulWidget {
const Customer({Key? key}) : super(key: key);
@override
_CustomerState createState() => _CustomerState();
}
class _CustomerState extends State<Customer> {
var db = DatabaseConnect();
void addItem(Todo todo) async {
await db.insertTodo(todo);
setState(() {});
}
void deleteItem(Todo todo) async {
await db.deleteTodo(todo);
setState(() {});
}
void updateItem(Todo todo) async {
await db.updateTodo(todo);
setState(() {});
}
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.white,
appBar: AppBar(
centerTitle: false,
title: const Padding(
padding: EdgeInsets.all(50.0),
child: Text(
'My Clients',
style: TextStyle(
fontSize: 24,
fontWeight: FontWeight.w600,
color: Colors.black),
),
),
backgroundColor: Colors.white,
elevation: 0,
actions: [
IconButton(
onPressed: () {
Navigator.of(context).pushReplacementNamed('/searchPage');
},
icon: const Icon(
Icons.search,
color: Colors.black,
),
),
]),
body: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Padding(
padding: EdgeInsets.symmetric(horizontal: 16, vertical: 10),
child: Text(
'Company Name',
style: TextStyle(fontSize: 14, fontWeight: FontWeight.w600),
),
),
CustomerList(
// insertFunction: addItem,
tobie: deleteItem,
stella: updateItem,
),
],

),
floatingActionButton: FloatingActionButton(
backgroundColor: Colors.lightBlueAccent,
child: const Icon(Icons.add),
onPressed: () {
showModalBottomSheet(
isScrollControlled: true,
context: context,
builder: (context) => CustomerProfile(insertFunction: addItem),
);
}),
floatingActionButtonLocation: FloatingActionButtonLocation.centerFloat,
);
}
}

下一个代码是我的CustomerList,我的ListviewBuilder检查要显示的客户数据。如果有,将详细信息传递给我的CustomerCard页面(并填充到卡片/ListTile中)。同样在我的CustomerList中,它通过Stella函数从Customer传递我的additem,通过CustomerList,通过CustomerCard,到我的EditPage:

CustomerList

import 'package:flutter/material.dart';
import 'library.dart';
import 'customercard.dart';
class CustomerList extends StatelessWidget {
final Function tobie;
final Function stella;
final db = DatabaseConnect();
CustomerList(
{required this.stella,
required this.tobie,

Key? key})
: super(key: key);
@override
Widget build(BuildContext context) {
return Expanded(
child: FutureBuilder(
future: db.getTodo(),
initialData: const [],
builder: (BuildContext context, AsyncSnapshot<List> snapshot) {
var data = snapshot
.data; // this is the data we have to show. (list of todo)
var datalength = data!.length;
return datalength == 0
? const Center(
child: Text('no data found'),
)
: ListView.builder(
itemCount: datalength,
itemBuilder: (context, i) => CustomerCard(
id: data[i].id,
title: data[i].title,
name: data[i].name,
phone: data[i].phone,
fax: data[i].fax,
email: data[i].email,
street: data[i].street,
city: data[i].city,
town: data[i].town,
code: data[i].code,
isExpanded: data[i].isExpanded,
// insertFunction: insertFunction,
janFunction: tobie,
simbaFunction: stella,
),
);
}),
);
}
}

下面是我的CustomerCard代码,它将数据填充到Card和ListTile中。再次,我的updateItem通过(simbfunction:stella):

传递CustomerCard

import 'package:flutter/material.dart';
import 'library.dart';
import 'package:test_sqlite/edit_input.dart';
class CustomerCard extends StatefulWidget {
final int id;
final String title;
final String name;
final String phone;
final String fax;
final String email;
final String street;
final String city;
final String town;
final String code;
bool isExpanded;
final Function janFunction;
final Function simbaFunction;
CustomerCard(
{required this.id,
required this.title,
required this.name,
required this.phone,
required this.fax,
required this.email,
required this.street,
required this.city,
required this.town,
required this.code,
required this.isExpanded,

required this.janFunction,
required this.simbaFunction,
Key? key})
: super(key: key);
@override
_CustomerCardState createState() => _CustomerCardState();
}
class _CustomerCardState extends State<CustomerCard> {
var db = DatabaseConnect();
@override
Widget build(BuildContext context) {
var anotherTodo = Todo(
id: widget.id,
title: widget.title,
name: widget.name,
phone: widget.phone,
fax: widget.fax,
email: widget.email,
street: widget.street,
city: widget.city,
town: widget.town,
code: widget.code,
isExpanded: widget.isExpanded);
return Card(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Theme(
data: Theme.of(context).copyWith(dividerColor: Colors.transparent),
child: ExpansionTile(
initiallyExpanded: false,
title: Text(
widget.title,
style: const TextStyle(
//fontWeight: FontWeight.bold,
fontSize: 16,
),
),
children: [
ListTile(
leading: const Icon(
Icons.person,
size: 20,
color: Colors.teal,
),
visualDensity: const VisualDensity(vertical: -3),
title: Text(
widget.name,
style: const TextStyle(
fontSize: 16,
fontWeight: FontWeight.normal,
color: Colors.black,
),
),
),
ListTile(
leading: const Icon(
Icons.phone,
size: 20,
color: Colors.teal,
),
visualDensity: const VisualDensity(vertical: -4),
title: Text(
widget.phone,
style: const TextStyle(
fontSize: 16,
fontWeight: FontWeight.normal,
color: Colors.black,
),
),
),
ListTile(
leading: const Icon(
Icons.report,
size: 20,
color: Colors.teal,
),
visualDensity: const VisualDensity(vertical: -4),
title: Text(
widget.fax,
style: const TextStyle(
fontSize: 16,
fontWeight: FontWeight.normal,
color: Colors.black,
),
),
),
ListTile(
leading: const Icon(
Icons.email,
size: 20,
color: Colors.teal,
),
visualDensity: const VisualDensity(vertical: -4),
title: Text(
widget.email,
style: const TextStyle(
fontSize: 16,
fontWeight: FontWeight.normal,
color: Colors.black,
),
),
),
ListTile(
leading: const Icon(
Icons.place,
size: 20,
color: Colors.teal,
),
visualDensity: const VisualDensity(vertical: -4),
title: Text(
widget.street,
style: const TextStyle(
fontSize: 16,
fontWeight: FontWeight.normal,
color: Colors.black,
),
),
),
ListTile(
leading: const Icon(
Icons.place,
size: 20,
color: Colors.teal,
),
visualDensity: const VisualDensity(vertical: -4),
title: Text(
widget.city,
style: const TextStyle(
fontSize: 16,
fontWeight: FontWeight.normal,
color: Colors.black,
),
),
),
ListTile(
leading: const Icon(
Icons.place,
size: 20,
color: Colors.teal,
),
visualDensity: const VisualDensity(vertical: -4),
title: Text(
widget.town,
style: const TextStyle(
fontSize: 16,
fontWeight: FontWeight.normal,
color: Colors.black,
),
),
),
ListTile(
leading: const Icon(
Icons.code,
size: 20,
color: Colors.teal,
),
visualDensity: const VisualDensity(vertical: -4),
title: Text(
widget.code,
style: const TextStyle(
fontSize: 16,
fontWeight: FontWeight.normal,
color: Colors.black,
),
),
),
Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
Padding(
padding: const EdgeInsets.all(8.0),
child: ElevatedButton(
onPressed: () {
showModalBottomSheet(
isScrollControlled: true,
context: context,
builder: (context) => EditPage(
nalaFunction: widget.simbaFunction,
variable: anotherTodo,
edit: '',
edit1: '',
edit2: '',
edit3: '',
edit4: '',
edit5: '',
edit6: '',
edit7: '',
edit8: '',
),
//updateFunction,
//),
);
},
style: ElevatedButton.styleFrom(
shape: const StadiumBorder(),
primary: Colors.white,
elevation: 0,
padding: const EdgeInsets.symmetric(
horizontal: 2, vertical: 2),
),
child: const Icon(
Icons.edit,
size: 20,
color: Colors.grey,
),
),
),
],
),
],
leading: const IconButton(
icon: Icon(
Icons.place,
color: Colors.blue,
size: 20,
),
onPressed: null,
alignment: Alignment.center,
),
trailing: IconButton(
onPressed: () {
widget.janFunction(anotherTodo);
},
icon: const Icon(
Icons.delete,
color: Colors.red,
size: 20,
),
),
),
),
],
),
);
}
}

最后,我的EditPage。当我打开它时,SQLite数据库中的现有客户数据自动正确显示。每个Textfield都有自己的onChanged。一旦我按下Elevated按钮,bottomModalSheet正确关闭(弹出),但新数据实际上并没有更新。这就是问题所在

EditPage

import 'package:flutter/material.dart';
import 'library.dart';
import 'package:flutter/cupertino.dart';
class EditPage extends StatelessWidget {
final Todo variable;
final Function nalaFunction;
String edit;
String edit1;
String edit2;
String edit3;
String edit4;
String edit5;
String edit6;
String edit7;
String edit8;
late final textController = TextEditingController(text: variable.title);
late final nameController = TextEditingController(text: variable.name);
late final phoneController = TextEditingController(text: variable.phone);
late final faxController = TextEditingController(text: variable.fax);
late final emailController = TextEditingController(text: variable.email);
late final streetController = TextEditingController(text: variable.street);
late final cityController = TextEditingController(text: variable.city);
late final townController = TextEditingController(text: variable.town);
late final codeController = TextEditingController(text: variable.code);
EditPage(

{Key? key,
required this.nalaFunction,
required this.variable,
required this.edit,
required this.edit1,
required this.edit2,
required this.edit3,
required this.edit4,
required this.edit5,
required this.edit6,
required this.edit7,
required this.edit8,
}) : super(key: key);
@override
Widget build(BuildContext context) {
return Container(
padding: const EdgeInsets.all(30.0),
decoration: const BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.only(
topLeft: Radius.circular(30.0),
topRight: Radius.circular(30.0),
),
),
child: Scaffold(
appBar: AppBar(
backgroundColor: Colors.white,
elevation: 0,
title: const Padding(
padding: EdgeInsets.all(15.0),
child: Text(
'Client Details',
style: TextStyle(color: Colors.black, fontSize: 24),
),
),
leading: GestureDetector(
onTap: () {
Navigator.of(context).pushReplacementNamed('/homePage');
},
child: const Icon(
Icons.arrow_back,
color: Colors.black,
),
),
),
body: SingleChildScrollView(
child: Container(
color: Colors.white,
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
TextField(
controller: textController,
autofocus: true,
textAlign: TextAlign.left,
decoration: const InputDecoration(
hintText: 'Company Name',
hintStyle: TextStyle(color: Colors.grey),
),
onChanged: (String? value) {
edit = value!;
},
),
TextField(
controller: nameController,
autofocus: true,
textAlign: TextAlign.left,
decoration: const InputDecoration(
hintText: ' Contact Name & Surname',
hintStyle: TextStyle(color: Colors.grey),
),
onChanged: (String? value1) {
edit1 = value1!;
},
),
TextField(
controller: phoneController,
autofocus: true,
textAlign: TextAlign.left,
decoration: const InputDecoration(
hintText: ' Contact Number',
hintStyle: TextStyle(color: Colors.grey),
),
onChanged: (String? value2) {
edit2 = value2!;
},
),
TextField(
controller: faxController,
autofocus: true,
textAlign: TextAlign.left,
decoration: const InputDecoration(
hintText: 'Fax Number',
hintStyle: TextStyle(color: Colors.grey),
),
onChanged: (String? value3) {
edit3 = value3!;
},
),
TextField(
controller: emailController,
autofocus: true,
textAlign: TextAlign.left,
decoration: const InputDecoration(
hintText: 'Email Address',
hintStyle: TextStyle(color: Colors.grey),
),
onChanged: (String? value4) {
edit4 = value4!;
},
),
TextField(
controller: streetController,
autofocus: true,
textAlign: TextAlign.left,
decoration: const InputDecoration(
hintText: 'Street Name',
hintStyle: TextStyle(color: Colors.grey),
),
onChanged: (String? value5) {
edit5 = value5!;
},
),
TextField(
controller: cityController,
autofocus: true,
textAlign: TextAlign.left,
decoration: const InputDecoration(
hintText: ' City',
hintStyle: TextStyle(color: Colors.grey),
),
onChanged: (String? value6) {
edit6 = value6!;
},
),
TextField(
controller: townController,
autofocus: true,
textAlign: TextAlign.left,
decoration: const InputDecoration(
hintText: 'Town',
hintStyle: TextStyle(color: Colors.grey),
),
onChanged: (String? value7) {
edit7 = value7!;
},
),
TextField(
controller: codeController,
autofocus: true,
textAlign: TextAlign.left,
decoration: const InputDecoration(
hintText: ' Code',
hintStyle: TextStyle(color: Colors.grey),
),
onChanged: (String? value8) {
edit8 = value8!;
},
),
ElevatedButton(
onPressed: () {
Navigator.pop(context);
var valueTodo = Todo(
title: edit,
name: edit1,
phone: edit2,
fax: edit3,
email: edit4,
street: edit5,
city: edit6,
town: edit7,
code: edit8,
isExpanded: false);
nalaFunction(valueTodo);
},
child: Padding(
padding: const EdgeInsets.fromLTRB(0, 10, 0, 0),
child: Container(
decoration: BoxDecoration(
color: Theme.of(context).primaryColor,
borderRadius: BorderRadius.circular(15),
),
padding: const EdgeInsets.symmetric(
horizontal: 25, vertical: 10),
child: const Text(
'Update',
textAlign: TextAlign.center,
style: TextStyle(
color: Colors.white,
fontWeight: FontWeight.bold,
),
),
),
),
),
],
),
),
),
),
);
}
}

我认为问题是:

  1. My function in My database is incorrect.
  2. 客户页面中的数据(updateItem)不与数据库中的updateTodo链接。
  3. updateItem数据通过所有小部件传递到EditPage不正确。
  4. 我的代码在EditPage (ElevatedButton onPressed是错误的)。
  5. 参数(edit ", edit1 "等)在CustomerCard页面路由到EditPage是错误的

我终于解决了这个问题。我已经用一个手势检测器替换了我的ElevatedButton,并从我的TextFields中删除了onchanged,从而也删除了我所有的编辑参数。

我的updateFunction和updateItem函数实际上一直工作得很好。我以前使用过onTap和变量(updateTodo)的gestredetector与我的textEditingControllers,但由于我不能使这个工作,我尝试了onChanged的ElevateButton,这也不起作用。所以,回到gestredetector,我意识到我从来没有给变量updateTodo分配一个id。我只有我的textedingcontroller。现在,在我的Sql数据库中,数据库使用'Where: id'更新,但由于我没有为我的文本分配'id',因此每次更新时我都有效地返回Null。

下面是修复之前GetureDetector的代码片段,

GestureDetector(
onTap: () {
Navigator.pop(context);
var updateTodo = Todo(

title: textController.text,
name: nameController.text,
phone: phoneController.text,
fax: faxController.text,
email: emailController.text,
street: streetController.text,
city: cityController.text,
town: townController.text,
code: codeController.text,
isExpanded: false);
nalaFunction(updateTodo);
},

和修复后的相同代码:

GestureDetector(
onTap: () {
Navigator.pop(context);
var updateTodo = Todo(
id: id,
title: textController.text,
name: nameController.text,
phone: phoneController.text,
fax: faxController.text,
email: emailController.text,
street: streetController.text,
city: cityController.text,
town: townController.text,
code: codeController.text,
isExpanded: false);
nalaFunction(updateTodo);
},

和将CustomerCard类中的'id'传递给EditPage的代码:

class CustomerCard extends StatefulWidget {
final int id;
final String title;
final String name;
final String phone;
final String fax;
final String email;
final String street;
final String city;
final String town;
final String code;
bool isExpanded;
final Function janFunction;
final Function simbaFunction;
CustomerCard(
{required this.id,
required this.title,
required this.name,
required this.phone,
required this.fax,
required this.email,
required this.street,
required this.city,
required this.town,
required this.code,
required this.isExpanded,

和.

Row(mainAxisAlignment: MainAxisAlignment.end,
children: [
Padding(
padding: const EdgeInsets.all(8.0),
child: ElevatedButton(
onPressed: () {
showModalBottomSheet(
isScrollControlled: true,
context: context,
builder: (context) => EditPage(
nalaFunction: widget.simbaFunction,
variable: anotherTodo,
id: widget.id,
),
//updateFunction,
//),
);
},

并将'id'传递给EditPage,以便可以被同一页面上的GestureDetector到达:

class EditPage extends StatelessWidget {
final Todo variable;
final Function nalaFunction;
final int id;
late final textController = TextEditingController(text: variable.title);
late final nameController = TextEditingController(text: variable.name);
late final phoneController = TextEditingController(text: variable.phone);
late final faxController = TextEditingController(text: variable.fax);
late final emailController = TextEditingController(text: variable.email);
late final streetController = TextEditingController(text: variable.street);
late final cityController = TextEditingController(text: variable.city);
late final townController = TextEditingController(text: variable.town);
late final codeController = TextEditingController(text: variable.code);
EditPage({Key? key,
required this.nalaFunction,
required this.variable,
required this.id,
}) : super(key: key);

这解决了我的问题,我的应用程序现在更新新的客户数据完美。

最新更新