[英]Flutter: How to access 'provider' values in a function outside the build context of the child widget?
The provider values are coming from the parent widget.提供者值来自父小部件。 I can use the provider values under the build context.
我可以在构建上下文下使用提供者值。 However I need the provider values in the getHomeCampaigns function.
但是我需要getHomeCampaigns function 中的提供程序值。 I tried to define local variables and assign them to the provider values once the widget is built, but the function claims that the variables are called on null.
一旦构建了小部件,我尝试定义局部变量并将它们分配给提供程序值,但是 function 声称这些变量是在 null 上调用的。 I guess they are being used before they are being set under the build context from the provider.
我猜它们是在提供者的构建上下文下设置之前被使用的。
class HomeScreen extends StatefulWidget {
@override
_HomeScreenState createState() => _HomeScreenState();
}
class _HomeScreenState extends State<HomeScreen> {
// Variables to be set inside the function and then used by the last widget
User currentUser;
String country;
List<CampaignWidget> friendsCamps;
List<CampaignWidget> featuredCamps;
// Function that needs the provider values
getHomeCampaigns() async {
// Get all campaigns where their owner is in the list of friends for the current user
QuerySnapshot friendsSnapshot = await Firestore.instance
.collection('campaigns')
.where('user.uid', whereIn: currentUser.friends)
.where('attributes.active', isEqualTo: true)
.orderBy('created', descending: true)
.limit(20)
.getDocuments();
// Get featured campaigns documents in the current country
QuerySnapshot featuredSnapshot = await Firestore.instance
.collection('campaigns')
.where('attributes.featured', isEqualTo: true)
.where('funders.${currentUser.uid}', isEqualTo: false)
.where('country', isEqualTo: country)
.orderBy('user.rating', descending: true)
.limit(5)
.getDocuments();
// Make 2 lists of CampaignWidget out of the documents retrieved
List<CampaignWidget> campaigns = friendsSnapshot.documents
.map((doc) => CampaignWidget(campaign: Campaign.fromDocument(doc)))
.toList();
List<CampaignWidget> featured = featuredSnapshot.documents
.map((doc) => CampaignWidget(campaign: Campaign.fromDocument(doc)))
.toList();
setState(() {
// Set the featured and friends lists of CampaignWidget to the newly made lists
this.featuredCamps = featured;
this.friendsCamps = campaigns;
});
}
@override
void initState() {
super.initState();
getHomeCampaigns();
}
@override
Widget build(BuildContext context) {
this.currentUser = Provider.of<User>(context);
this.country = Provider.of<String>(context);
return Scaffold(
backgroundColor: Color(0xFFE8E8E8),
appBar: AppBar(
centerTitle: false,
title: Text("Home"),
actions: <Widget>[
/// Search users
IconButton(
icon: Icon(
Icons.search,
),
onPressed: () {},
),
],
),
body: RefreshIndicator(
onRefresh: () => getHomeCampaigns(),
child: // Some widget that uses the variables,
),
);
}
}
You can read the variables from your provider like this: Provider.of(context, listen: false).yourVariable
in getHomeCampaigns
.您可以像这样从您的提供者读取变量:
Provider.of(context, listen: false).yourVariable
in getHomeCampaigns
。 You must have listen: false
for this to work though because it is not in the widget tree so it can't update whenever yourVariable
changes -- see.你必须有
listen: false
才能工作,因为它不在小部件树中,所以每当yourVariable
更改时它就无法更新 - 请参阅。 If this doesn't work there is a problem where you declare you provider.如果这不起作用,则在您声明您的提供者时会出现问题。
I moved from my api being an inheritedWidget to a provider.我从作为一个继承小部件的 api 转移到提供者。 "The Flutter Complete Reference" suggested to avoid inheritWidget because of complexity.
“Flutter 完整参考”建议避免由于复杂性而使用inheritWidget。 I start at the materialapp and wrap it around my api class containing my restful calls.
我从 materialapp 开始,将它包裹在我的 api class 周围,其中包含我的宁静通话。 I use the counter to see that the button has been pressed.
我使用计数器查看按钮已被按下。 Now, I can access my api calls in all objects in the materialapp tree.
现在,我可以在 materialapp 树中的所有对象中访问我的 api 调用。
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'My app',
theme: ThemeData(
primarySwatch: Colors.blue,
),
debugShowCheckedModeBanner: false,
home: Provider<Api>(
create: (context) => Api(),
child: Home(title: 'my title')));
}
}
class Home extends StatefulWidget {
Home({Key key, @required this.title}) : super(key: key);
final String title;
@override
_HomeState createState() => _HomeState();
}
class _HomeState extends State<Home> {
int _counter = 0;
onLogin(BuildContext context) {
LoginView param = new LoginView("abc@com",
"xxx");
Provider.of<Api>(context, listen: false)
.addLogin(context, param)
.then((value) {
setState(() {
_counter++;
});
}).catchError((error) {
DialogCaller.showErrorDialog(context,
error.toString()).then((value) {});
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Example'),
),
body: Container(
child: Column(
children: [
TextButton.icon(
label: Text("abc"),
icon: Icon(Icons.web),
onPressed: () {
onLogin(context);
setState(() {
_counter++;
});
}),
Text(
'$_counter',
style:
Theme.of(context).textTheme.headline4,
)
],
)));
}
}
You should take a look at Riverpod .你应该看看Riverpod 。 It fills out provider caveats, and gives you a bunch of new capabilities.
它填补了供应商的注意事项,并为您提供了许多新功能。 You can access 'provider' values and functions defined in the class without context.
您可以在没有上下文的情况下访问 class 中定义的“提供者”值和函数。 It also allows you to have multiple 'providers' of the same type.
它还允许您拥有多个相同类型的“提供者”。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.