【问题标题】:Flutter pass provider as an argumentFlutter 将提供程序作为参数传递
【发布时间】:2022-01-05 04:13:29
【问题描述】:

我有一个 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(),
        ),
      )
  );

不行,怎么办?


使用解决方案编辑 我在路由器中添加了消费者:

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(),
        ),
      )
  );

【问题讨论】:

    标签: flutter dart provider


    【解决方案1】:

    我不确定我是否理解这个案例,但我只是告诉一个想法它是否有效,如果我理解你的问题: 在您的路线通行证提供者到 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 与您收到的每个内容的提供者一起使用:

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

    可能是我误会了

    【讨论】:

    • 成功了,感谢您的宝贵时间!我编辑我的帖子。
    猜你喜欢
    • 2020-09-09
    • 2021-11-06
    • 2020-01-19
    • 2011-10-21
    • 2020-05-20
    • 2020-09-19
    • 1970-01-01
    • 2014-05-24
    • 1970-01-01
    相关资源
    最近更新 更多