简体   繁体   English

Flutter:如何在子小部件的构建上下文之外访问 function 中的“提供者”值?

[英]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.

相关问题 Flutter 如何在构建小部件之外使用上下文? - Flutter how to use context outside build widget? Flutter:从小部件树外部访问提供者 - Flutter: access provider from outside the widget tree 我有一个关于在“Widget build(BuildContext context) {}”之外的函数内初始化提供程序的问题。 - I have a question about initializing the provider inside a function outside the 'Widget build(BuildContext context) {}.' 如何在其 function flutter 之外访问 function 集合提供程序中的变量 - How to access a variable in a function set provider outside its function flutter 在 Flutter 中,如何在构建上下文之外访问来自 Modal route.of(context) (Named Route) 的参数,例如在函数或初始化状态中 - In Flutter how to access arguments from Modal route.of(context) (Named Route) outside the build context for example in function or init state 如何在颤振中将上下文传递给子小部件 - How to pass context to a child widget in flutter Flutter 如何在没有上下文的情况下访问提供者 - How to Access Provider with out Context in Flutter 通过 addPostFrameCallback 的 Flutter Provider 访问表示小部件在小部件树之外,但 flutter inspector 显示否则 - Flutter Provider access via addPostFrameCallback says widget is outside the widget tree but flutter inspector shows otherwise 如何对访问 Provider.of(context) 的小部件进行 Flutter 测试 - How to do a Flutter Test for a widget that accesses Provider.of(context) 如何在Flutter中访问父级中的子控件的数据? - How to access data of child widget in parent in flutter?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM