在对话框中使用 BLoC:找不到正确的提供程序

Nef*_*ous 9 dialog flutter bloc

我正在尝试使用块来管理对话框的内容。我对扑动相当陌生。

该页面定义为:

@override
Widget build(BuildContext context) {
  return Scaffold(
    appBar: AppBar(
      title: Text("Business Region Manager"),
    ),
    body: MultiBlocProvider(
      providers: [
        BlocProvider(
          create: (context) =>
              EntityModifyBloc(repository: widget.repository),
        ),
        BlocProvider(
          create: (context) => EntityBloc(
              repository: widget.repository,
              modifyBloc: BlocProvider.of<EntityModifyBloc>(context)),
        ),
        BlocProvider(
          create: (context) => BusinessRegionBloc(repository: widget.repository),
        ),
      ],
      child: Center(
        child: BusinessRegionPage(widget.business),
      ),
    ));
}
Run Code Online (Sandbox Code Playgroud)

在 BusinessRegionPage 内部,我使用了 EntityBloc 和 EntityModifyBloc,并且,我至少认为我的做法是正确的。该页面有一个回调,当触发时会调用一个方法:

void onAddBusinessRegion(){
  showDialog(context: context,
    barrierDismissible: false,
    builder: (BuildContext context){
      return BusinessRegionDialog(
        positiveText: "Ok",
        onPositive: onPositive,
        negativeText: 'Cancel',
        onNegative: onNegative,
        businessId: widget.business.id,
      );
    });
}
Run Code Online (Sandbox Code Playgroud)

BusinessRegionDialog 是一个有状态的小部件,状态实现构建是:

@override
Widget build(BuildContext context) {
  return BlocBuilder<BusinessRegionBloc, BusinessRegionState>(builder: (context, state) {
    if (state is BusinessRegionEmpty) {
      BlocProvider.of<BusinessRegionBloc>(context).add(GetBusinessRegions(widget.businessId));
    }
    if (state is BusinessRegionError) {
      return Center(
        child: Text('Busines Region Error'),
      );
    }
    if (state is BusinessRegionLoaded) {
      return Center(
        child: Text('BusinessRegionLoaded'),
      );
    }
    return Center(
      child: CircularProgressIndicator(),
    );
  });
Run Code Online (Sandbox Code Playgroud)

当回调被触发时,我收到消息:

错误:在此 BlocBuilder<BusinessRegionBloc, BusinessRegionState> 小部件上方找不到正确的提供程序

发生这种情况可能是因为您使用的提供商BuildContext不包括您选择的提供商。

我假设在调用 ShowDialog(context) 时,上下文与传递到 build 的上下文相同?我通过在 showDialog 调用之前和 BusinessRegionPage 上的构建实现之后打印上下文的 hashCode 来检查这个假设,

错误消息中的建议之一是:

Widget build(BuildContext context) {
  return Provider<Example>(
    create: (_) => Example(),
    builder: (context) {
      return Text(context.watch<Example>()),
    }
  ),
}
Run Code Online (Sandbox Code Playgroud)

所以我尝试了:

void onAddBusinessRegion() {
  print("OnAddCallback: " + context.hashCode.toString());
  BusinessRegionClient brClient = BusinessRegionClient(client: http.Client());
  BusinessRegionRepository brRepository =
      BusinessRegionRepository(client: brClient);

  showDialog(
    context: context,
    barrierDismissible: false,
    builder: (BuildContext context) {
      return Provider<BusinessRegionBloc>(
          create: (_) => BusinessRegionBloc(repository: brRepository),
          builder: (context) {
            return BusinessRegionDialog(
              positiveText: "Ok",
              onPositive: onPositive,
              negativeText: 'Cancel',
              onNegative: onNegative,
              businessId: widget.business.id,
            );
          });
    });
}
Run Code Online (Sandbox Code Playgroud)

IDE 告诉我:参数类型“BusinessRegionDialog Function(BuildContext)”无法分配给参数类型“Widget Function(BuildContext, Widget)”。

我显然不明白什么。我想做的就是用我的存储库中的 Future 信息填充一个对话框。任何指导将不胜感激。

zex*_*oor 5

BlocProvider.value在构建器参数中使用showDialog

onPress: () async {
        await showDialog(
          context: context,
          builder: (_) {
            return BlocProvider.value(
              value: BlocProvider.of<BlocA>(context),
              child: SimpleDialogWidget(),
            );
          },
        );
      }
Run Code Online (Sandbox Code Playgroud)


Nef*_*ous 3

I finally figured it out thanks to the so entry:

Flutter: bloc, how to show an alert dialog

这里的答案是使用堆栈使对话框和页面共存,并在侦听器具有正确状态时显示对话框。答案使用 StatelessWidget 来管理(在答案的情况下),即 SnackBar。为了能够向块添加事件,我使用了 StatefulWidget。

@override
Widget build(BuildContext context) {
  return Scaffold(
    appBar: AppBar(
    title: Text("Business Region Manager"),
    ),
    body: MultiBlocProvider(
      providers: [
        BlocProvider(
          create: (context) => EntityModifyBloc(
              repository: xbrRepository), //widget.repository),
        ),
        BlocProvider(
          create: (context) => EntityBloc(
              repository: xbrRepository, //widget.repository,
              modifyBloc: BlocProvider.of<EntityModifyBloc>(context)),
        ),
        BlocProvider(
          create: (context) => BusinessRegionDialogBloc(
              repository: xbrRepository),
        ),
      ],
      child: Stack(children: [
        BusinessRegionDialogManager(widget.business.id),
        Center(child: BusinessRegionPage(widget.business)),
      ]),
    ));
}

class BusinessRegionDialogManager extends StatefulWidget {
  final int businessId;

  BusinessRegionDialogManager(this.businessId);

  State<BusinessRegionDialogManager> createState() =>
    _BusinessRegionDialogManagerState();
}


class _BusinessRegionDialogManagerState
extends State<BusinessRegionDialogManager> {

// Callback functions from the dialog so can have access to
// BusinessRegionDialogBloc
void xnPositive(List<Region> addedRegions) {
    BlocProvider.of<BusinessRegionDialogBloc>(context)
      .add(AddBusinessRegions(addedRegions, widget.businessId));
}

void xnNegative(){
}


@override
Widget build(BuildContext context) {
  return BlocListener<BusinessRegionDialogBloc, BusinessRegionDialogState>(
    listener: (context, state) {
      if (state is RegionDialogLoaded) {
        showDialog(
          context: context,
          barrierDismissible: false,
          builder: (BuildContext context) {
            return BusinessRegionDialog(
              onPositive: xnPositive,
              onNegative: xnNegative,
              regions: state.regions,
            );
          })
      }
    },
    child: Container(),
  );
}
Run Code Online (Sandbox Code Playgroud)