Flutter从凸起按钮的onPressed调用FutureBuilder不会调用builder属性

时间:2018-11-29 15:55:14

标签: dart flutter

我正在尝试学习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');
    }
}

很明显我遗漏了一些东西,但是知道我在做什么错吗?

3 个答案:

答案 0 :(得分:5)

如果要从请求中获取一些数据,则不需要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'),
        )

答案 1 :(得分:1)

onPressed中的RaisedButton方法实际上什么也没做。它只是创建一个新的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(/*...*/});中进行更改打电话。

答案 2 :(得分:0)

对我而言,FutureBuilder无法在onPresses上运行... 我用这种方式:

我定义了一个状态为

的变量
    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中。我把它放在身体上,并在返回结果后更改了可见性。