0

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

 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'

4

1 回答 1

0

因为它在 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) {
 .....

其中 _myFuture 在 initState() 处进行评估:

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.
        }
      },
    );
  }
于 2020-12-14T22:21:41.190 回答