【问题标题】:Flutter, calling FutureBuilder from a raised button's onPressed doesn't call the builder propertyFlutter,从凸起按钮的 onPressed 调用 FutureBuilder 不会调用 builder 属性
【发布时间】:2018-11-29 15:55:13
【问题描述】:

我正在尝试学习 Dart/Flutter,并且正在研究一个示例,其中应用程序上有一个显示“获取数据”的按钮,当我触摸它时,我想从一个安静的服务中检索 JSON 数据。

我看到在 fetchPost 中调用了 Web 服务,但未调用 FutureBuilder 的 builder 属性。

import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'ResultsList.dart';
import 'dart:convert';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Restul Test',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);
  final String title;

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  int _counter = 0;

  void _incrementCounter() {
    setState(() {
      _counter++;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            RaisedButton(
              onPressed: (){
                FutureBuilder<ResultsList>(
                  future: fetchPost(),
                  builder: (context, snapshot){
                    print('In Builder');
                  }
                );
              },
              child: Text('Get data'),
            )
          ],
        ),
      )
    );
  }
}

Future<ResultsList> fetchPost() async {
    final response =  await http.get('http://mywebserviceurl');

    if (response.statusCode == 200){
      print('Received data');
      return ResultsList.fromJson(json.decode(response.body));
    }
    else {
      throw Exception('Failed to load data');
    }
}

但有趣的是,如果我将 FutureBuilder 从按钮的 onPressed 移到 Center 的子级,我确实看到 builder 属性被调用。

import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'ResultsList.dart';
import 'dart:convert';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Restul Test',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);
  final String title;

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  int _counter = 0;

  void _incrementCounter() {
    setState(() {
      _counter++;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: FutureBuilder<ResultsList>(
                future: fetchPost(),
                builder: (context, snapshot){
                  print ('In Builder');
                  return Container();
                }
              )
      )
    );
  }
}

Future<ResultsList> fetchPost() async {
    final response =  await http.get('http://mywebserviceurl');

    if (response.statusCode == 200){
      print('Received data');
      return ResultsList.fromJson(json.decode(response.body));
    }
    else {
      throw Exception('Failed to load data');
    }
}

显然我错过了什么,但知道我做错了什么吗?

【问题讨论】:

  • 这段代码没有意义。在onPressed 中使用setState(...) 更新状态,然后在调用构建时您可以使用FutureBuilder 或根本不使用FutureBuilder 并在onPressed 中使用async/await 并调用@987654330 @异步执行完成时。
  • FutureBuilder 是一个小部件,而不是一个函数。它必须在小部件树中

标签: dart flutter


【解决方案1】:

如果您想从请求中获取一些数据 - 您不需要 FutureBuilder。你可以这样做:

RaisedButton(
          onPressed: (){
            fetchPost().then((result) {
                print('In Builder');
            })
          },
          child: Text('Get data'),
        )

RaisedButton(
          onPressed: () async {
            var result = await fetchPost()
            print('In Builder');
          },
          child: Text('Get data'),
        )

【讨论】:

  • 谢谢...浪费了时间。使用 FutureBuilder 有什么好处吗?
  • 如果您从异步请求中获取一些数据,然后您必须显示小部件 - 那么您需要 FutureBuilder。例如,您必须在某些小部件中显示fetchPost 请求的结果
  • @AndreyTurkovsky 有什么方法可以在等待未来时显示进度指示器吗?
  • @ZohaibTariq 可以更新状态并显示指标,接收数据后隐藏。但最好使用 StreamBuilder。或 FutureBuilder
【解决方案2】:

这个RaisedButton 中的onPressed 方法实际上没有做任何事情。它只是创建了一个新的FutureBuilder,除了现有的之外什么都不做^^这就像你只是调用1+1;,它只是创建一个值,但该值不用于做任何事情。

RaisedButton(
  onPressed: (){
    FutureBuilder<ResultsList>(
      future: fetchPost(),
      builder: (context, snapshot){
        print('In Builder');
      }
    );
  },
  child: Text('Get data'),
)

您可以将body 分配给Widget(可以直接称为body 或您想要的任何名称^^),然后您可以在setState((){body = FutureBuilder(/*...*/}); 调用中对其进行更改。

【讨论】:

    【解决方案3】:

    对我来说,FutureBuilder 不能在 onPresses 中工作...... 我是这样用的:

    我在 state 中定义了一个变量:

        bool visiblity = false;
    

    我在构建中使用了这段代码:

      @override
      Widget build(BuildContext context) {
        return Scaffold(
         appBar: AppBar(
          title: Text(widget.title),
        ),
        body: Center(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: <Widget>[
              RaisedButton(
                onPressed: () {
                  visiblity=true;
                  fetchPost();
                },
                child: Text('Get data'),
              ),
              FutureBuilder<ResultsList>(
                  future: ("Your View Model that return from call back"),
                  builder: (context, snapshot) {
                    if (visiblity) {
                      print('In Builder');
                      visiblity=false;
                    } else
                      return Container();
                  }
              ),
            ],
          ),
        )
       );
      }
    

    我没有将 FutureBuilder 放入 onPressed。我把它放在正文中,并在返回结果后改变了可见性。

    【讨论】:

      猜你喜欢
      • 2020-04-02
      • 2019-04-20
      • 2020-01-07
      • 2023-03-05
      • 1970-01-01
      • 1970-01-01
      • 2020-06-05
      • 2021-12-18
      • 2019-01-21
      相关资源
      最近更新 更多