22

我在一个小部件树中有一个 FloatingActionButton ,它有一个BlocProviderfrom flutter_bloc。像这样的东西:

BlocProvider(
  builder: (context) {
    SomeBloc someBloc = SomeBloc();
    someBloc.dispatch(SomeEvent());

    return someBloc;
  },
  child: Scaffold(
    body: ...
    floatingActionButton: FloatingActionButton(
      onPressed: _openFilterSchedule,
      child: Icon(Icons.filter_list),
    ),
  )
);

打开一个模态底部表:

void _openFilterSchedule() {
    showModalBottomSheet<void>(
      context: context,
      builder: (BuildContext context) {
        return TheBottomSheet();
      },
    );
  }

我正在尝试SomeBloc使用BlocProvider.of<SomeBloc>(context)inside访问,TheBottomSheet但出现以下错误:

BlocProvider.of() called with a context that does not contain a Bloc of type SomeBloc.

我尝试使用https://stackoverflow.com/a/56533611/2457045BottomSheet中描述的解决方案,但仅适用于ModalBottomSheet.


注意:这不限于BlocProvideror flutter_bloc提供程序包中的任何提供程序都具有相同的行为。

如何访问BlocProvider.of<SomeBloc>(context)内部showModalBottomSheet

如果无法做到这一点,如何使https://stackoverflow.com/a/56533611/2457045解决方案适应模态底页?

4

6 回答 6

45

InheritedWidgets 以及提供者的范围都在小部件树中。不能在该树之外访问它们。

问题是,使用showDialog和类似的功能,对话框位于不同的小部件树中 - 它可能无法访问所需的提供程序。

因此,有必要在新的小部件树中添加所需的提供程序:

void myShowDialog() {
  final myModel = Provider.of<MyModel>(context, listen: false);
  showDialog(
    context: context,
    builder: (_) {
      return Provider.value(value: myModel, child: SomeDialog());
    },
  );
}
于 2019-08-18T20:41:42.237 回答
6

您需要将 Provider 移到顶层(MaterialApp)

根据图片,对话框小部件在 MaterialApp 下,所以这就是你使用错误上下文的原因

在此处输入图像描述

于 2020-02-18T02:20:40.563 回答
3

提供者showModalBottomSheet(底页)

void myBottomSheet() {
  final myModel = Provider.of<MyModel>(context, listen: false);
  showModalBottomShee(
    context: context,
    builder: (_) {
      return ListenableProvider.value(
        value: myModel,
        child: Text(myModel.txtValue),
      );
    },
  );
}
于 2020-08-26T07:52:32.607 回答
0

我找到了一个解决方案,只需使用 StatefulBuilder 返回您的 showModalBottomSheet 并使用您的 modalsheet 构建器的上下文传递给您的提供者。下面是我的代码片段:

Future<Widget> showModal(int qty, Product product) async {
    return await showModalBottomSheet(
        isScrollControlled: true,
        backgroundColor: Colors.transparent,
        context: context,
        builder: (BuildContext ctx) {
          return StatefulBuilder(builder: (ctx, state) {
             return Container(
                  child: RaisedButton(
                          onPressed: () {
                             Product prod = Product(product.id, 
                                         product.sku, product.name, qty);
                             Provider.of<CartProvider>(ctx, listen: 
                                        false).addCart(prod);}),);
    }
  }
);
}
于 2020-08-18T03:33:47.517 回答
0

您应该将 Scaffold 小部件及其子级拆分为另一个 StatefulWidget

从单个小部件

class MainScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return BlocProvider(
      builder: (context) {
        SomeBloc someBloc = SomeBloc();
        someBloc.dispatch(SomeEvent());
        return someBloc;
      },
      child: Scaffold(
        body: ...
        floatingActionButton: FloatingActionButton(
          onPressed: _openFilterSchedule,
          child: Icon(Icons.filter_list),
        ),
      )
    );
  }
}

分成这两个小部件

class MainScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return BlocProvider(
      builder: (context) {
        SomeBloc someBloc = SomeBloc();
        someBloc.dispatch(SomeEvent());
        return someBloc;
      },
      child: Screen(),
    );
  }
}

和 ..

class Screen extends StatelessWidget {

  void _openFilterSchedule() {
    showModalBottomSheet<void>(
      context: context,
      builder: (BuildContext context) {
        return TheBottomSheet();
      },
    );
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: ...
      floatingActionButton: FloatingActionButton(
        onPressed: _openFilterSchedule,
        child: Icon(Icons.filter_list),
      ),
    );
  }
}
于 2019-08-18T19:58:32.020 回答
-2

在处理 showModelBottomSheet 时遇到了同样的问题,因为它恰好在不同的(上下文)小部件树中工作,我必须将我的状态升级到应用程序的状态,以便我可以使用上下文访问我的提供程序。

代码片段

于 2021-10-28T11:23:35.993 回答