我是Flutter的超级菜鸟,我正在尝试“琐碎的”(对于其他所有人) CRUD应用程序,因此我遵循了一些教程
(https://grokonez.com/android/flutter-sqlite-example-listview-crud-operations-sqflite-plugin)
他的“版本”显然有效,当然我的无效。 我收到此错误:https://i.stack.imgur.com/TM893.png
这是“我的”代码,我猜其中涉及的部分是DBHelper和TicketScreen:
class DatabaseHelper {
static final DatabaseHelper _instance = new DatabaseHelper.internal();
factory DatabaseHelper() => _instance;
final String ticketTable = 'ticketTable';
final String columnId = 'id';
final String columnDay = 'day';
final String columnMonth = 'month';
final String columnYear = 'year';
final String columnFrom = 'from';
final String columnTo = 'to';
final String columnAircraft = 'aircraft';
final String columnAirline = 'airline';
static Database _db;
DatabaseHelper.internal();
Future<Database> get db async {
if (_db != null) {
return _db;
}
_db = await initDb();
return _db;
}
initDb() async {
String databasesPath = await getDatabasesPath();
String path = join(databasesPath, 'ticket.db');
var db = await openDatabase(path, version: 1, onCreate: _onCreate);
return db;
}
void _onCreate(Database db, int newVersion) async {
await db.execute(
'CREATE TABLE $ticketTable($columnId INTEGER PRIMARY KEY, $columnDay TEXT, $columnMonth TEXT, $columnYear TEXT, $columnFrom TEXT, $columnTo TEXT, $columnAircraft TEXT, $columnAirline TEXT)');
}
Future<int> saveTicket(Ticket ticket) async {
var dbClient = await db;
var result = await dbClient.insert(ticketTable, ticket.toMap());
return result;
}
Future<List> getAllTickets() async {
var dbClient = await db;
var result = await dbClient.query(ticketTable, columns: [
columnId,
columnDay,
columnMonth,
columnYear,
columnFrom,
columnTo,
columnAircraft,
columnAirline
]);
return result.toList();
}
Future<int> getCount() async {
var dbClient = await db;
return Sqflite.firstIntValue(
await dbClient.rawQuery('SELECT COUNT(*) FROM $ticketTable'));
}
Future<Ticket> getTicket(int id) async {
var dbClient = await db;
List<Map> result = await dbClient.query(ticketTable,
columns: [
columnId,
columnDay,
columnMonth,
columnYear,
columnFrom,
columnTo,
columnAircraft,
columnAirline
],
where: '$columnId = ?',
whereArgs: [id]);
if (result.length > 0) {
return new Ticket.fromMap(result.first);
}
return null;
}
Future<int> deleteTicket(int id) async {
var dbClient = await db;
return await dbClient
.delete(ticketTable, where: '$columnId = ?', whereArgs: [id]);
}
Future<int> updateTicket(Ticket ticket) async {
var dbClient = await db;
return await dbClient.update(ticketTable, ticket.toMap(),
where: "$columnId = ?", whereArgs: [ticket.id]);
}
Future close() async {
var dbClient = await db;
return dbClient.close();
}
}
class TicketScreen extends StatefulWidget {
final Ticket ticket;
TicketScreen(this.ticket);
@override
State<StatefulWidget> createState() => new _TicketScreenState();
}
class _TicketScreenState extends State<TicketScreen> {
DatabaseHelper db = new DatabaseHelper();
TextEditingController _dayController;
TextEditingController _monthController;
TextEditingController _yearController;
TextEditingController _fromController;
TextEditingController _toController;
TextEditingController _aircraftController;
TextEditingController _airlineController;
@override
void initState() {
super.initState();
_dayController = new TextEditingController(text: widget.ticket.day);
_monthController = new TextEditingController(text: widget.ticket.month);
_yearController = new TextEditingController(text: widget.ticket.year);
_fromController = new TextEditingController(text: widget.ticket.from);
_toController = new TextEditingController(text: widget.ticket.to);
_aircraftController = new TextEditingController(text: widget.ticket.aircraft);
_airlineController = new TextEditingController(text: widget.ticket.airline);
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Ticket')),
body: Container(
margin: EdgeInsets.all(15.0),
alignment: Alignment.center,
child: Column(
children: <Widget>[
Text('Travel Date',
style: new TextStyle(fontWeight: FontWeight.bold),
),
Row(
children: <Widget>[
Container(
alignment: Alignment.center,
width: 80.0,
child: TextField(
maxLength: 2,
keyboardType: TextInputType.number,
controller: _dayController,
decoration: InputDecoration(labelText: 'Day'),
),
),
Text(' / '),
Container(
width: 80.0,
child: TextField(
maxLength: 2,
keyboardType: TextInputType.number,
controller: _monthController,
decoration: InputDecoration(labelText: 'Month'),
),
),
Text(' / '),
Container(
width: 160.0,
child: TextField(
maxLength: 4,
keyboardType: TextInputType.number,
controller: _yearController,
decoration: InputDecoration(labelText: 'Year'),
),
),
],
),
Padding(padding: new EdgeInsets.all(5.0)),
Row(
children: <Widget>[
Container(
width: 160.0,
child: TextField(
controller: _fromController,
decoration: InputDecoration(labelText: 'From'),
),
),
Container(
width: 160.0,
child: TextField(
controller: _toController,
decoration: InputDecoration(labelText: 'To'),
),
),
],
),
Padding(padding: new EdgeInsets.all(5.0)),
Row(
children: <Widget>[
Container(
width: 160.0,
child: TextField(
controller: _aircraftController,
decoration: InputDecoration(labelText: 'Aircraft'),
),
),
Container(
width: 160.0,
child: TextField(
controller: _airlineController,
decoration: InputDecoration(labelText: 'Airline'),
),
),
],
),
Padding(padding: new EdgeInsets.all(5.0)),
RaisedButton(
child: (widget.ticket.id != null) ? Text('Update') : Text('Add'),
onPressed: () {
if (widget.ticket.id != null) {
db
.updateTicket(Ticket.fromMap({
'id': widget.ticket.id,
'day': _dayController.text,
'year': _yearController.text,
'from': _fromController.text,
'to': _toController.text,
'aircraft': _aircraftController.text,
'airline': _airlineController.text
}))
.then((_) {
Navigator.pop(context, 'update');
});
} else {
db
.saveTicket(Ticket(
_dayController.text,
_monthController.text,
_yearController.text,
_fromController.text,
_toController.text,
_aircraftController.text,
_airlineController.text))
.then((_) {
Navigator.pop(context, 'save');
});
}
},
),
],
),
),
);
}
}
然后是其他一些东西,但我倾向于排除它们是问题的根源
class MyListView extends StatefulWidget {
@override
_ListViewState createState() => new _ListViewState();
}
class _ListViewState extends State<MyListView> {
List<Ticket> items = new List();
DatabaseHelper db = new DatabaseHelper();
@override
void initState() {
super.initState();
db.getAllTickets().then((tickets) {
setState(() {
tickets.forEach((ticket) {
items.add(Ticket.fromMap(ticket));
});
});
});
}
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Ticket List',
home: Scaffold(
appBar: AppBar(
title: Text('Ticket List'),
centerTitle: true,
backgroundColor: Colors.blue,
),
body: Center(
child: ListView.builder(
itemCount: items.length,
padding: const EdgeInsets.all(15.0),
itemBuilder: (context, position) {
return Column(
children: <Widget>[
Divider(height: 5.0),
ListTile(
title: Text(
'From ${items[position].from} to ${items[position].to}',
style: TextStyle(
fontSize: 22.0,
color: Colors.deepOrangeAccent,
),
),
subtitle:
Text(
'Operated by ${items[position].airline} with ${items[position].aircraft} ',
style: new TextStyle(
fontSize: 18.0,
fontStyle: FontStyle.italic,
),
),
leading: Column(
children: <Widget>[
Padding(padding: EdgeInsets.all(10.0)),
CircleAvatar(
backgroundColor: Colors.blueAccent,
radius: 20.0,
child: Text(
'${items[position].day}/${items[position].month}/${items[position].year}',
style: TextStyle(
fontSize: 22.0,
color: Colors.white,
),
),
),
IconButton(
icon: const Icon(Icons.remove_circle_outline),
onPressed: () => _deleteTicket(context, items[position], position)
),
],
),
onTap: () => _navigateToTicket(context, items[position]),
),
],
);
}),
),
floatingActionButton: FloatingActionButton(
child: Icon(Icons.add),
onPressed: () => _createNewTicket(context),
),
),
);
}
void _deleteTicket(BuildContext context, Ticket ticket, int position) async {
db.deleteTicket(ticket.id).then((tickets) {
setState(() {
items.removeAt(position);
});
});
}
void _navigateToTicket(BuildContext context, Ticket ticket) async {
String result = await Navigator.push(
context,
MaterialPageRoute(builder: (context) => TicketScreen(ticket)),
);
if (result == 'update') {
db.getAllTickets().then((tickets) {
setState(() {
items.clear();
tickets.forEach((ticket) {
items.add(Ticket.fromMap(ticket));
});
});
});
}
}
void _createNewTicket(BuildContext context) async {
String result = await Navigator.push(
context,
MaterialPageRoute(builder: (context) => TicketScreen(Ticket('', '', '', '', '', '', ''))),
);
if (result == 'save') {
db.getAllTickets().then((tickets) {
setState(() {
items.clear();
tickets.forEach((ticket) {
items.add(Ticket.fromMap(ticket));
});
});
});
}
}
}
class Ticket {
int _id;
String _day;
String _month;
String _year;
String _from;
String _to;
String _aircraft;
String _airline;
Ticket(this._day, this._month, this._year, this._from, this._to, this._aircraft, this._airline);
Ticket.map(dynamic obj) {
this._id = obj['id'];
this._day = obj['day'];
this._month = obj['month'];
this._year = obj['year'];
this._from = obj['form'];
this._to = obj['to'];
this._aircraft = obj['aircraft'];
this._airline = obj['airline'];
}
int get id => _id;
String get day => _day;
String get month => _month;
String get year => _year;
String get from => _from;
String get to =>_to;
String get aircraft =>_aircraft;
String get airline => _airline;
Map<String, dynamic> toMap() {
var map = new Map<String, dynamic>();
if (_id != null) {
map['id'] = _id;
}
map['day'] = _day;
map['month'] = _month;
map['year'] = _year;
map['from'] = _from;
map['to'] = _to;
map['aircraft'] = _aircraft;
map['airline'] = _airline;
return map;
}
Ticket.fromMap(Map<String, dynamic> map) {
this._id = map['id'];
this._day = map['day'];
this._month = map['month'];
this._year = map['year'];
this._from = map['from'];
this._to = map['to'];
this._aircraft = map['aircraft'];
this._airline = map['airline'];
}
}
void main() => runApp(
MaterialApp(
title: 'Returning Data',
home: MyListView(),
),
);
那么,你能告诉我我做错了什么吗? 预先谢谢你
奖金问题: 我不喜欢SQL, 有没有其他可供选择的分贝? 我的意思是真正的数据库,不是将数据保存在sharedpref或使用Firebase, 我喜欢领域,但看起来好像没有动静。
再次感谢
答案 0 :(得分:1)
问题是您在列名中使用了保留关键字'From',同时还使用了'To'
'CREATE TABLE $ticketTable($columnId INTEGER PRIMARY KEY, $columnDay TEXT, $columnMonth TEXT, $columnYear TEXT, $columnFrom TEXT, $columnTo TEXT, $columnAircraft TEXT, $columnAirline TEXT)');
因此,本质上您是在要求它创建一个名为TicketTable的表,该表具有以下列名-id,day,month,year ..,其中包含这些特定的数据类型。但是,当到达名为“ from”的列时,它认为您想从名为“ Text”的表中创建一个空值(因为列名不存在),这没有任何意义。
以下是您应避免使用的关键字列表-https://docs.oracle.com/database/121/SQLRF/ap_keywd001.htm#SQLRF55621
您也许可以通过用双引号将变量引起来来解决此问题,但是您必须自己进行测试。