当我从api获取数据时,我正在从ui调用数据库帮助程序类,并且该数据必须转储到数据库中才能在应用程序中脱机使用。我收到此错误。我在哪里收到此错误,以及为什么未初始化数据库并允许我对其执行操作。
错误:
I/flutter ( 5420): NoSuchMethodError: The method 'insert' was called on null.
I/flutter ( 5420): Receiver: null
I/flutter ( 5420): Tried calling: insert("Deliveries", _LinkedHashMap len:6, conflictAlgorithm: Instance of 'ConflictAlgorithm')
E/flutter ( 5420): [ERROR:flutter/lib/ui/ui_dart_state.cc(157)] Unhandled Exception: NoSuchMethodError: The method 'query' was called on null.
E/flutter ( 5420): Receiver: null
E/flutter ( 5420): Tried calling: query("Deliveries")
E/flutter ( 5420): #0 Object.noSuchMethod (dart:core-patch/object_patch.dart:53:5)
E/flutter ( 5420): #1 TodoHelper.getAllTask (package:delivery_app_odoo_flutter/utils/db_todays_deliveries_model.dart:110:55)
E/flutter ( 5420): #2 _TodayDeliveriesState.inertInDb (package:delivery_app_odoo_flutter/ui/deliveries_page/today_deliveries_page.dart:49:22)
E/flutter ( 5420): <asynchronous suspension>
E/flutter ( 5420): #3 SchedulerBinding._invokeFrameCallback (package:flutter/src/scheduler/binding.dart:1102:15)
E/flutter ( 5420): #4 SchedulerBinding.handleDrawFrame (package:flutter/src/scheduler/binding.dart:1049:9)
E/flutter ( 5420): #5 SchedulerBinding._handleDrawFrame (package:flutter/src/scheduler/binding.dart:957:5)
E/flutter ( 5420): #6 _rootRun (dart:async/zone.dart:1126:13)
E/flutter ( 5420): #7 _CustomZone.run (dart:async/zone.dart:1023:19)
E/flutter ( 5420): #8 _CustomZone.runGuarded (dart:async/zone.dart:925:7)
E/flutter ( 5420): #9 _invoke (dart:ui/hooks.dart:259:10)
E/flutter ( 5420): #10 _drawFrame (dart:ui/hooks.dart:217:3)
E/flutter ( 5420):
型号:
对于toMap方法中的项目,转换逻辑是否正确?因为我们必须将其转换为字符串才能存储到本地数据库中。
class TodayDeliveriesModel extends Equatable{
String address;
String CustomerName;
String orderNumber;
String total;
List<ItemsModel> allItems;
bool pending;
TodayDeliveriesModel({this.address, this.CustomerName,this.orderNumber, this.allItems, this.total, this.pending});
Map<String, dynamic> toMap(){
return {
Column_address : this.address,
Column_CustomerName:this.CustomerName,
Column_orderNumber:this.orderNumber,
Column_total:this.total,
Column_allItems:this.allItems?.map((e) =>
e == null ? null : ItemsModel(quantity: e.quantity,name: e.name))
?.toList(),
Column_pending:this.pending
};
}
@override
List<TodayDeliveriesModel> get props => deliveriesList;
}
从UI调用(有状态的小部件):
@override
void initState() {
// TODO: implement initState
super.initState();
TodoHelper.dba.initDatabase();
todayDeliveries=TodayDeliveriesModel();
listProp = todayDeliveries.props;
// todoHelper=TodoHelper();
insertDataInDB();
}
insertDataInDB()async{
await TodoHelper.dba.insertTask(listProp);
WidgetsBinding.instance.addPostFrameCallback(getFromDb);
}
void getFromDb(Duration timeStamp) async{
await TodoHelper.dba.getAllTask().then((val){
setState(() {
val.forEach((v){
dbList.add(v);
});
});
});
}
数据库帮助程序类:
class TodoHelper{
Database _db;
TodoHelper._();
static final TodoHelper dba = TodoHelper._();
Future<Database> get database async {
if (_db != null) return _db;
// if _database is null we instantiate it
_db = await initDatabase();
return _db;
}
Future initDatabase() async{
return await openDatabase(
join(await getDatabasesPath(), "test.db"),
onCreate: (db, version)async{
// return _createDb(db);
await db.execute("CREATE TABLE $tableName($Column_id INTEGER PRIMARY KEY AUTOINCREMENT, $Column_address TEXT, $Column_CustomerName TEXT, $Column_orderNumber TEXT, $Column_total TEXT,$Column_allItems TEXT,$Column_pending TEXT)");
},
version: 1
);
}
Future<void> insertTask(List<TodayDeliveriesModel> task) async{
final Database = await _db;
try{
task.forEach((val){
Database.insert(tableName, val.toMap(), conflictAlgorithm: ConflictAlgorithm.replace);
});
}catch(_){
print(_);
}
}
Future<List<TodayDeliveriesModel>> getAllTask () async{
final List<Map<String, dynamic>> tasks = await _db.query(tableName);
return List.generate(tasks.length, (i){
return TodayDeliveriesModel(address: tasks[i][Column_address],total: tasks[i][Column_total],allItems: tasks[i][Column_allItems],
CustomerName:tasks[i][Column_CustomerName] ,orderNumber: tasks[i][Column_orderNumber],pending: tasks[i][Column_pending] );
});
}
}
答案 0 :(得分:0)
initDatabase()
是async
,但在ToDoHelper
中没有等待它。您在这里遇到的问题是initDatabase()
在构造函数中,不能为async
或不能使用await
。我有一个类似的类来处理我的apps数据库,该数据库等待需要DB,然后打开数据库并将其保存到_db
变量中,或者如果以前曾使用过数据库,则返回_db
变量开了之所以有效,是因为它可以确保在尝试访问数据库之前已返回正确的期货。
如果从构造函数中删除initDatabase()
,并用以下私有变量和异步getter替换Database db;
,则数据库应能按预期工作。
static Database _db;
// If there is no database in place then initialise one
Future<Database> get db async {
if (_db != null) {
return _db;
}
// Initialise db
_db = await initDatabase();
return _db;
}
您还将确保始终执行await db
而不只是db
。因此,在上面的示例中,db.insert(...)
周围的代码可能变为
final database = await db;
task.forEach((val){
database.insert(tableName, val.toMap(), conflictAlgorithm: ConflictAlgorithm.replace);
});