如何在 Flutter 的 Dialogs 中访问 Provider 提供者

Jus*_*ain 16 flutter inherited-widget flutter-provider

Provider 包使用InheritedWidget. 当我在对话框中时想访问提供程序时,这是一个问题。如果我使用加载对话框

 showDialog(... builder: (context) => MyDialog);
Run Code Online (Sandbox Code Playgroud)

我无法访问任何东西,InheritedWidget因为我的对话框不是主小部件树的一部分。这也意味着我无法访问我的 Provider 提供商,对吗?

我的问题是:如果它不是主应用程序小部件树的一部分,我如何在对话框中访问我的提供程序?

final firebaseAuth = Provider.of<FirebaseAuth>(context);
Run Code Online (Sandbox Code Playgroud)

我在使用BLoCs. 如果我尝试在对话框中通过 检索它们InheritedWidget,它们将失败。我已经通过BLoC在构造函数中传递了来解决这个问题,但这似乎违背了InheritedWidgets.

Ste*_*veM 8

您可以使用 BlocProvider.value,而不是在构造函数中传递 BLoC。

https://pub.dev/documentation/flutter_bloc/latest/flutter_bloc/BlocProvider/BlocProvider.value.html

这将允许您将现有的 BLoC 实例提供给新路由(对话框)。你仍然可以享受所有的好处InheritedWidget

  // Get the BLoC using the provider
  MyBloc myBloc = BlocProvider.of<MyBloc>(context);

  showDialog(
    context: context,
    builder: (BuildContext context) {
      Widget dialog = SimpleDialog(
        children: <Widget>[
          ... // Now you can call BlocProvider.of<MyBloc>(context); and it will work
        ],
      );

      // Provide the existing BLoC instance to the new route (the dialog)
      return BlocProvider<MyBloc>.value(
        value: myBloc, //
        child: dialog,
      );
    },
  );
Run Code Online (Sandbox Code Playgroud)

.value() 也适用于 ChangeNotifierProvider、ListenableProvider 等。 https://pub.dev/documentation/provider/latest/provider/ChangeNotifierProvider/ChangeNotifierProvider.value.html

https://pub.dev/documentation/provider/latest/provider/ListenableProvider/ListenableProvider.value.html


小智 5

我在这部分卡住了一段时间。老实说,我不想传递提供程序,当您处理复杂的小部件时,解压缩小部件代码以获取父上下文也很困难(而且这似乎不是最好的方法)。

这更有意义

  handleFileViewerClicked(context) async {
    var reportState = Provider.of<ReportState>(context, listen: false);
    /**
     *The dialog will live in a new context and requires a new provider to be created for the report state
     * For more information read the Provider.Consumer documentation and showDialog function signature.
     */
    showDialog(
      context: context,
      //Notice the use of ChangeNotifierProvider<ReportState>.value
      builder: (_) => ChangeNotifierProvider<ReportState>.value(
        value: reportState,
        child: FileViewer(),
      ),
    );
}
Run Code Online (Sandbox Code Playgroud)

在这种情况下,您的孩子小部件是 FileViewer 可以使用

class FileViewer extends StatelessWidget {
.
.
Widget build(BuildContext context) {
    //you can enable or disable listen if you logic require so 
    var reportState = Provider.of<ReportState>(context); 
    return Text('${reportState.files.length}');
 }
}
Run Code Online (Sandbox Code Playgroud)


Eri*_*ett 1

我能够通过将数据集传递到警报对话框中来访问提供程序数据。有趣的是,您必须在对话框中调用 setState() 才能看到对话框中的更改。

class _MyHomePageState extends State<MyHomePage> {
  @override
  Widget build(BuildContext context) {

    final provider = Provider.of<DataSet>(context);

    return Scaffold(
      body: Container(
        child: RaisedButton(
        child: Text('Show Dialog'),
          onPressed: () {
            showDialog(context: context,
            builder: (context) {
              return DialogContent(dataSet: provider);
            });
          },
        ),
      ),
    );
  }
}

class DialogContent extends StatefulWidget {

  final DataSet dataSet;

  const DialogContent({Key key, this.dataSet}) : super(key: key);

  @override
  _DialogContentState createState() => _DialogContentState();
}

class _DialogContentState extends State<DialogContent> {
  @override
  Widget build(BuildContext context) {
    return AlertDialog(
      title: Text('Dialog with data'),
      content: Text('${widget.dataSet.pieceOfData}'),
      actions: <Widget>[
        FlatButton(
          child: Text('Increase Data'),
          onPressed: () {
            setState(() {
              widget.dataSet.increaseData();
            });
          },
        ),
      ],
    );
  }
}

class DataSet with ChangeNotifier {
  int pieceOfData = 1;

  increaseData() {
    pieceOfData += 1;
    notifyListeners();
  }
}
Run Code Online (Sandbox Code Playgroud)