【问题标题】:Flutter : why future builder run more than one timeFlutter:为什么未来的构建器运行不止一次
【发布时间】:2020-12-14 11:32:14
【问题描述】:

我的页面包含未来的构建器以从共享偏好中获取用户名:

 Widget build(BuildContext context) {
    return Consumer<ProductProvider>(builder: (context, prod, child) {
      return FutureBuilder(
          future: Services().get_user(),
          builder: (context, snapshot) {
            if (snapshot.hasData) {
              var name = snapshot.data['name'];
              return OrderDetails(name);
            } else {
              return Container();
            }
          });
    });
  }

该页面的小部件包含另一个未来构建器,具体取决于通过页面传递的名称值:

class OrderDetails extends StatelessWidget {
  final name;
  const OrderDetails(this.name);
  @override
  Widget build(BuildContext context) {
    return FutureBuilder(
      future: Services().get_orders(name),
      builder: (context, snapshot) {
        if (snapshot.data != null) {
          print('snapshot.data.length  ${snapshot.data.length}'); // ------ it is print 6
          return ListView.builder(
            itemCount: snapshot.data.length,
            itemBuilder: (context, index) {
              return Text('user_id');
            },
          );
        } else {
          return Container();
        }
      },
    );
  }

Services().get_orders(name) 方法:

get_orders(name) async {
    var url = 'http://10.0.2.2:8000/api/user/myorder/$name';
    var response = await http.get(url);
    var data = jsonDecode(response.body);
    return (data);
  }

我将数据放在数据库中,就是这样:

{
  "id": 3,
  "user_id": 24,
  "status": "ordered",
  "order_item": [
    {
      "id": 11,
      "order_id": 3,
      "product_id": 1,
      "quantity": 2,
    },
    {
      "id": 12,
      "order_id": 3,
      "product_id": 2,
      "quantity": 1,
    }
  ]
}

结果,它运行了 6 次,并打印 'user_id'

【问题讨论】:

  • 您是否在任何地方的小部件中使用过setState()
  • 不是所有的都是无状态的
  • 您能否将完整的 JSON 数据粘贴到您的问题中
  • snapshot.data.length的值是多少
  • 我放的是完整的Json数据,长度为6

标签: flutter flutter-futurebuilder


【解决方案1】:

因为它在 build() 方法中使用。 这不是问题……如果您不评估其中的 Future 方法。 我的意思是,你不应该这样做:

Widget build(BuildContext context) {
    return FutureBuilder(
      future: Services().get_orders(name),
      builder: (context, snapshot) {
 .....

但是这个:

Widget build(BuildContext context) {
    return FutureBuilder(
      future: _myFuture,
      builder: (context, snapshot) {
 .....

在 initState() 处评估 _myFuture 的位置:

class OrderDetails extends StatefullWidget {
@override
_OrderDetailsState createState() => _OrderDetailsState();

}
class _OrderDetailsState extends State<OrderDetails> {

  final name;
  
  Future _myFuture;

  @override
  void initState() {
     name = widget.name;
     _myFuture = Services().get_orders(name); //this method is async, thus do not slow down the init state: the result is still not ready.
     super.initState();
   }


  const OrderDetails(this.name);
  @override
  Widget build(BuildContext context) {
    return FutureBuilder(
      future: _myFuture,  //the FutureBuilder will wait until the _myFuture will get the results from Services().get_orders(...)
      builder: (context, snapshot) {
        if (snapshot.hasFinished ) { //better test: data is always not null. at least with zero data.
          print('snapshot.data.length  ${snapshot.data.length}'); // ------ it is print 6
          return ListView.builder(
            itemCount: snapshot.data.length,
            itemBuilder: (context, index) {
              return Text('user_id');
            },
          );
        } else {
          return CircularProgressIndicator(); // a circular progress indicator is the quickest way to tell the user we are waiting for data.
        }
      },
    );
  }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-06-05
    • 2019-03-19
    • 1970-01-01
    • 1970-01-01
    • 2013-06-25
    • 2023-03-17
    • 2011-09-29
    • 1970-01-01
    相关资源
    最近更新 更多