Flutter 将提供者作为参数传递

Flutter pass provider as an argument

我有一个 TemplateView 页面,其中包含一个内容参数,该参数承载根据我的应用程序而变化的内容。 每个内容都有一个特定的提供者。 另一方面,我的 TemplateView 页面有一个按钮,它调用每个提供者通用的验证函数。

这是我的应用示例(绿色是我的 TemplateView,红色是更改的内容):

这里是模板视图的简化代码。我们看到对内容的调用和调用内容提供者 ContentView1 的验证按钮。

class TemplateView extends StatelessWidget{
  final String title;
  final StatelessWidget content;
  TemplateView ({
        Key? key,
        required this.title,
        required this.content,
        required this.validationMessage,
      }) : super(key: key);

  @override
  Widget build(BuildContext context)
  {
    return GestureDetector(
      onTap: (() => FocusScope.of(context).requestFocus(FocusNode())),
      child: SafeArea(
        child: Scaffold(
          appBar: AppBar(
            title: Text(title),
          ),
          body : _buildBody(context),
        ),
      ),
    );
  }

  Widget _buildBody(BuildContext context)
  {
    // Here the call of my provider for the ContentView1
    var _messageProvider = Provider.of<ContentView1Provider>(context);

    return Column(
      children: [
        SingleChildScrollView(
          child: Container(
            child: content,
          ),
        ),
        InkWell(
            child: Container(
              child: Text('SAVE'),
            ),
            onTap: () => _messageProvider.validation()
        ),
      ],
    );
  }
}

在这里,我如何在路由器中调用 TemplateView:

case RouterName.kContentView1:
  return CupertinoPageRoute(
      builder: (context) => ChangeNotifierProvider<ContentView1Provider>(
        create: (BuildContext context) => ContentView1Provider(),
        child: TemplateView(
            title: "Content 1 page",
            message: ContentView1(),
        ),
      )
  );

一切正常,现在就像我说的内容会改变,但我的 TemplateView 是通用的。因此,我无法在 TemplateView 中直接输入对提供商的调用,因为它会根据页面而变化。

所以我想在 TemplateView 设置中调用提供者,但它不起作用。

我的新模板视图:

class TemplateView extends StatelessWidget{
  final String title;
  final StatelessWidget content;
  final Function validationMessage; // => I added this line
  TemplateView({
        Key? key,
        required this.title,
        required this.content,
        required this.validationMessage, // => I added this line
      }) : super(key: key);

  @override
  Widget build(BuildContext context)
  {
    // => I remove the call of the provider line
    return GestureDetector(
      onTap: (() => FocusScope.of(context).requestFocus(FocusNode())),
      child: SafeArea(
        child: Scaffold(
          appBar: AppBar(
            title: Text(title),
          ),
          body : _buildBody(context),
        ),
      ),
    );
  }

  Widget _buildBody(BuildContext context)
  {
    return Column(
      children: [
        SingleChildScrollView(
          child: Container(
            child: content,
          ),
        ),
        InkWell(
            child: Container(
              child: Text('SAVE'),
            ),
            onTap: () => validationMessage() // => I changed this line
        ),
      ],
    );
  }
}

我的新路由器:

case RouterName.kContentView1:
  return CupertinoPageRoute(
      builder: (context) => ChangeNotifierProvider<ContentView1Provider>(
        create: (BuildContext context) => ContentView1Provider(),
        child: TemplateView(
            title: "Content 1 page",
            message: Content1View(),
            validationMessage: () => Provider.of<ContentView1Provider>(context).validation(),
        ),
      )
  );

不行,怎么办?


编辑解决方案 我在路由器中添加了 Consumer :

case RouterName.kContentView1:
  return CupertinoPageRoute(
      builder: (context) => ChangeNotifierProvider<ContentView1Provider>(
        create: (BuildContext context) => ContentView1Provider(),
        child: TemplateView(
            title: "Content 1 page",
            message: Consumer<ContentView1Provider>(builder :(ctx , provider , child){
              return ContentView1();
            }),
            validationMessage: () => Provider.of<ContentView1Provider>(context).validation(),
        ),
      )
  );

我不确定我是否理解这个案例,但我只是告诉一个想法它是否可行以及我是否理解你的问题: 在您的路线传递供应商到 Tamplate 页面:

case RouterName.kContentView1:
  return CupertinoPageRoute(
      builder: (context) => ChangeNotifierProvider<ContentView1Provider>(
        create: (BuildContext context) => ContentView1Provider(),
        child: TemplateView(
            provider : ContentView1Provider ,     // add this line
            title: "Content 1 page",
            message: Content1View(),
            validationMessage: () => Provider.of<ContentView1Provider>(context).saveMessage(),
        ),
      )
  );

在模板视图中接收此提供商:

class TemplateView extends StatelessWidget{
  final provider;       //  add this line
  final String title;
  final StatelessWidget content;
  final Function validationMessage; // => I added this line
  TemplateView({
        Key? key,
        required this.provider,       //  add this line
        required this.title,
        required this.content,
        required this.validationMessage, // => I added this line
      }) : super(key: key);

现在您可以将 Consumer 与您收到的每个内容的 provider 一起使用:

return Consumer<provider>(builder :(ctx , provider , child){
   return //what you want ....;
})

可能是我理解错了