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 ....;
})
可能是我理解错了
我有一个 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 ....;
})
可能是我理解错了