Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/dart/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Flutter 找不到正确的提供程序<;X>;在这个ModalBottomSheet小部件上面_Flutter_Dart_Flutter Provider - Fatal编程技术网

Flutter 找不到正确的提供程序<;X>;在这个ModalBottomSheet小部件上面

Flutter 找不到正确的提供程序<;X>;在这个ModalBottomSheet小部件上面,flutter,dart,flutter-provider,Flutter,Dart,Flutter Provider,我不熟悉flifter,我正在尝试了解如何在一个应用程序中使用提供者状态管理,该应用程序允许用户Moor将一些数据保存到sqlite表中。我的应用程序是一个任务录制应用程序。当我打开我的底部工作表添加任务时,我的小部件树中出现了上述错误。我正在使用提供程序:^4.3.1 class TaskView extends StatelessWidget { DateTime selectedDate = DateTime.now(); @override Widget build(Bui

我不熟悉flifter,我正在尝试了解如何在一个应用程序中使用提供者状态管理,该应用程序允许用户
Moor
将一些数据保存到
sqlite
表中。我的应用程序是一个任务录制应用程序。当我打开我的底部工作表添加任务时,我的小部件树中出现了上述错误。我正在使用
提供程序:^4.3.1

class TaskView extends StatelessWidget {
  DateTime selectedDate = DateTime.now();

  @override
  Widget build(BuildContext context) {
    return Provider<TaskViewModel>(
        create: (_) => TaskViewModel(),
        child: Scaffold(
            appBar: AppBar(
              title: Text('Tasks'),
            ),
            body: Text("Temporary body!"),
            floatingActionButton: FloatingActionButton(
              onPressed: () {
                showMaterialModalBottomSheet(
                  context: context,
                  builder: (context, scrollController) => Container(
                    child: bottomSheet(context),
                  ),
                );
              },
              child: Icon(
                Icons.add,
                color: Colors.white,
              ),
              backgroundColor: Colors.blueAccent,
            )
        )
    );
  }

  Widget bottomSheet(BuildContext context) {
    return Padding(
      padding: EdgeInsets.only(
          left: 16.0,
          top: 16.0,
          right: 16.0,
          bottom: 16.0 + MediaQuery.of(context).viewInsets.bottom),
      child: Column(
        mainAxisSize: MainAxisSize.min,
        children: <Widget>[
          TextField(
            decoration: InputDecoration(
              border: OutlineInputBorder(),
              labelText: 'Task',
            ),
          ),
          SizedBox(height: 8),
          TextField(
            readOnly: true,
            decoration: InputDecoration(
              border: OutlineInputBorder(),
              suffixIcon: IconButton(
                icon: Icon(Icons.date_range, color: Colors.grey),
                onPressed: () => _selectDate(context),
              ),
              labelText: 'Date',
            ),
          ),
          SizedBox(height: 8),
          Align(
              alignment: Alignment.topRight,
              child: context.watch<TaskViewModel>().state == ViewState.IDLE
                  ? FlatButton(
                      child: Text("Save"),
                      color: Colors.blueAccent,
                      textColor: Colors.white,
                      onPressed: () => _onClickInsertTask(context))
                  : _loadingButtonChild(context))
        ],
      ),
    );
  }

  Widget _loadingButtonChild(BuildContext context) {
    return Container(
      height: 20,
      width: 20,
      margin: EdgeInsets.all(5),
      child: CircularProgressIndicator(
          strokeWidth: 2,
          valueColor: AlwaysStoppedAnimation<Color>(Colors.white)),
    );
  }

  /// This function is responsible for displaying the date picker when user click
  /// on task due date inputFiled
  Future<Null> _selectDate(BuildContext context) async {
    final DateTime picked = await showDatePicker(
        context: context,
        initialDate: selectedDate,
        firstDate: DateTime(2015, 8),
        lastDate: DateTime(2101));

    if (picked != null && picked != selectedDate) {
      print("Date selected ${selectedDate.toString()}");
    }
  }

  /// This function is responsible for triggering insert task block event
  void _onClickInsertTask(BuildContext context) {

    var insertTask = TaskData(task: "task", dueDate: selectedDate);
    context.read<TaskViewModel>().insertTask(insertTask);
  }
}
仍然会得到相同的错误。这里要注意的另一件事是下面建议的错误

Widget build(BuildContext context) {
    return Provider<Example>(
      create: (_) => Example(),
      // we use `builder` to obtain a new `BuildContext` that has access to the provider
      builder: (context) {
        // No longer throws
        return Text(context.watch<Example>()),
      }
    ),
  }
TaskViewModel

class BaseViewModel extends ChangeNotifier {

  ViewState _state = ViewState.IDLE;

  ViewState get state => _state;

  void setState(ViewState viewState) {
    _state = viewState;
    notifyListeners();
  }
}
class TaskViewModel extends BaseViewModel{

  final TaskRepository _repository = TaskRepository();

  Resource<int> insertTaskStatus;

  Future<void> insertTask(TaskData task) async {

    setState(ViewState.PROCESSING);
    var tasksCompanion = TasksCompanion(task: Value(task.task),dueDate: Value(task.dueDate));
    insertTaskStatus  = await  _repository.insertTask(tasksCompanion);
    setState(ViewState.COMPLETED);

  }

}
class TaskViewModel扩展了BaseViewModel{
最终TaskRepository_repository=TaskRepository();
资源插入任务状态;
Future insertTask(TaskData任务)异步{
设置状态(ViewState.PROCESSING);
var tasksCompanion=tasksCompanion(任务:Value(task.task),dueDate:Value(task.dueDate));
insertTaskStatus=wait_repository.insertTask(tasksCompanion);
设置状态(ViewState.COMPLETED);
}
}

尽管您在由
提供程序
包装的
支架
中调用
showMaterialModalBottomSheet
,但
提供程序
并不在
任务视图
支架和
modalBottomSheet
之上。为什么?

您试图读取的提供程序位于不同的路径中

因此,
modalBottomSheet
似乎位于不同的
路线上,上面没有
提供者。如果您看一下的实现,您将看到:

返回Navigator.of(上下文,rootNavigator:useRootNavigator).推送(_ModalBottomSheetRoute(..);

显然,这是一条新的
路线
。因此,要访问
提供者
,它应该位于两条
路线
之上。由于
模块底部工作表
路线
MaterialApp
管理,您必须将
提供者
置于
MaterialApp
之上


Provider
默认情况下使用
延迟加载
。因此,对象是在需要时创建的,而不是在应用程序启动时创建的。但是,如果您不希望出现这种行为,可以单独设置
lazy:false
。有关更多信息,请查看。

将您的提供程序放在MaterialApp上方。您可以解释为什么需要这种方法来导入Element?。如果我这样做,不是所有的屏幕都会出现这种情况吗?这样不是所有的Viemodel对象都会在应用程序启动时创建。不过,我的提供者位于小部件树的顶部,所以应该可以正常工作。但不是在这种情况下。哦,这就解释了错误。从这个答案中,我假设你在颤振方面有更多的经验。请对此进行解释。那么,一般来说,在现实世界的应用程序开发中,是否为材料应用程序提供了所有提供程序?就像这里使用的
MultiProvider
。我的问题是,它不是创建了所有提供程序(ViewModel)应用程序上的对象启动并产生性能问题?否。provider的一个功能是延迟加载,即它将在需要时创建对象,而不是在应用程序启动时创建对象。如果您转到所提供链接中的自述部分,您将发现“延迟加载”指定。@chathurangashanjayarathna所以这是正确的方法。是的,我看到了那个部分,但没有在我的大脑中点击它。谢谢你的帮助。我必须等待16小时才能给悬赏。我会给你的。
class TaskViewModel extends BaseViewModel{

  final TaskRepository _repository = TaskRepository();

  Resource<int> insertTaskStatus;

  Future<void> insertTask(TaskData task) async {

    setState(ViewState.PROCESSING);
    var tasksCompanion = TasksCompanion(task: Value(task.task),dueDate: Value(task.dueDate));
    insertTaskStatus  = await  _repository.insertTask(tasksCompanion);
    setState(ViewState.COMPLETED);

  }

}