flutter - NoSuchMethodError:在 null 上调用了方法“查询”。(虽然它将项目带到 UI)
问题描述
问题总结
我一直在堆栈上并且经常看到这个问题,我尝试了我能找到的所有解决方案,但它对我不起作用。我正在从我的sqflite
数据库中检索一些数据,有时它会获取结果,有时却没有,这似乎很奇怪。我读过你不应该init()
在Database
.
据说这是错的
import 'package:sqflite/sqflite.dart';
import 'package:path_provider/path_provider.dart';
class TaskDbProvider {
Database db;
TaskDbProvider(){
init()
}
init() async {...}
}
我如何得到上面代码的工作示例。(虽然在我的新方法中它似乎不起作用)
他们的解决方案
听一个Completer()
流
class TaskDbProvider {
Database db;
var readyCompleter = Completer();
Future get ready => readyCompleter.future;
TaskDbProvider(){
init().then((_) {
// mark the provider ready when init completes
readyCompleter.complete();
});
}
}
虽然这会触发一个新的异常链,如果需要我可以提供。
错误
[ERROR:flutter/lib/ui/ui_dart_state.cc(177)] Unhandled Exception: NoSuchMethodError: The method 'query' was called on null.
E/flutter (29065): Receiver: null
E/flutter (29065): Tried calling: query("Task")
E/flutter (29065): #0 Object.noSuchMethod (dart:core-patch/object_patch.dart:51:5)
E/flutter (29065): #1 TaskDbProvider.fetchTaskList (package:oppo/resources/db_provider.dart:51:47)
51 号线
Future<List<Task>> fetchTaskList() async{
List<Map<String,dynamic>> list = await db.query('Task'); //line 51 (db is null?)
return List.generate(list.length, (i) {
return Task.fromDb(list[i]);
});
}
我如何初始化数据库
创建 BLoC(稍后将添加一些额外的功能)
class BlocSpeech {
final cache = TaskDbProvider();
}
InheritedWidget
通过(又名提供商)使其可用
class SpeechProvider extends InheritedWidget{
final BlocSpeech bloc ;
static BlocSpeech of(BuildContext context){
return (context.inheritFromWidgetOfExactType(SpeechProvider) as SpeechProvider).bloc;
}
SpeechProvider({Key key, Widget child})
: bloc = BlocSpeech(),
super(key: key,child: child);
@override
bool updateShouldNotify(covariant InheritedWidget oldWidget) {
// TODO: implement updateShouldNotify
return true;
}
}
用户界面小部件
用提供者包装小部件
SpeechProvider(child: Work())
并构建小部件:
class Work extends StatefulWidget {
@override
_Work createState() => _Work();
}
class _Work extends State<Work> {
List<Task> allTasks=[];
@override
Widget build(BuildContext context) {
final SpeechBloc = SpeechProvider.of(context); //initialize the BLoC
final Future<List<Task>> future = SpeechBloc.cache.fetchTaskList(); //wait to fetch the items
future.then((value) => allTasks=value); //assign them to local variable
return ListView.builder(
padding: const EdgeInsets.all(8),
itemCount: (allTasks.length),
itemBuilder: (BuildContext context, int index) {
return Container(
margin: EdgeInsets.only(top: 10, bottom: 10),
child: _taskWidget(index,SpeechBloc));
});
}
如果需要,我会添加任何额外的信息。
解决方案
“Called on null”通常意味着您在未来的通话中抢先一步。确保 API 中所有“返回 Future”或“异步”的内容都在返回 Future 的方法中,并且每次调用返回 Future 的方法都受到 await 的保护。当您更仔细地理解时,有些地方可以省略其中的一些,但这是一个很好的第一次尝试。
推荐阅读
- javascript - 无法发布 HTML 表单数据和重定向
- javascript - 反应
没有得到更新或改变其状态 - sequelize.js - Sequelize - hasMany 缓慢地获取具有许多关系的一个
- python - 为什么要在语言中使用复制功能?
- dotnetnuke - 2sxc 暂存和实时版本未呈现
- python - 从维基百科中获取属于一个主题的文章的正确命题
- reactjs - 盖茨比:通过道具传递图像
- flutter - 如何以真实大小的图片弹出到 Gridview.builder
- selenium - Selenium:使用 selenium 登录返回 400(错误请求),但手动登录时返回 200
- python - JSONDecodeError 期望值:第 1 行第 1 列