首页 > 解决方案 > 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();
    });
  }
}

虽然这会触发一个新的异常链,如果需要我可以提供。

github链接

错误

[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));
        });
  }

如果需要,我会添加任何额外的信息。

标签: flutterdart

解决方案


“Called on null”通常意味着您在未来的通话中抢先一步。确保 API 中所有“返回 Future”或“异步”的内容都在返回 Future 的方法中,并且每次调用返回 Future 的方法都受到 await 的保护。当您更仔细地理解时,有些地方可以省略其中的一些,但这是一个很好的第一次尝试。


推荐阅读