【问题标题】:snapshot.ConnectionState always waitingsnapshot.ConnectionState 总是在等待
【发布时间】:2019-02-15 13:55:59
【问题描述】:

FutureBuilder中,snapshot.ConnectionState一直在等待,但是future函数成功完成。在不同的页面中,相同的代码块可以工作,ConnectionState 从等待变为完成。

未来功能:

Future getDoctors() async {
    var res = await http.get(globals.domain + "users/docs/");
    var resBody = json.decode(utf8.decode(res.bodyBytes));

    print(res.statusCode);

    if (res.statusCode == 200) {
      if (mounted) {
        setState(() {
          doctors = resBody;
        });
      }
    }
  }

未来的建设者:

FutureBuilder(
    future: getDoctors(),
    builder: (BuildContext context, snapshot) {
        print(snapshot);
    }
)

实际结果: AsyncSnapshot<dynamic>(ConnectionState.waiting, null, null) 预期结果:转至 AsyncSnapshot<dynamic>(ConnectionState.done, null, null)

编辑1: 在调试时注意到未来函数getDoctors() 会定期调用,我想这就是快照总是在等待的原因

【问题讨论】:

  • 你能在两个页面中展示你是如何使用它们的吗?
  • @MazinIbrahim 两个页面都一样,未来的功能也差不多dart @override Widget build(BuildContext context) { return Scaffold( body: FutureBuilder( future: getDoctors(), builder: (BuildContext context, snapshot) { print(snapshot); if (snapshot.connectionState == ConnectionState.waiting) { return Center(child: CircularProgressIndicator()); } if (snapshot.connectionState == ConnectionState.done) { return Center(...); }

标签: dart flutter


【解决方案1】:

调用setState 会导致小部件树被重建。因此,在重建FutureBuilder时,再次调用getDoctors()函数,导致死循环(getDoctors()->setState()->rebuild->getDoctors()...)

解决方案是从getDoctors 方法中删除setState 或在initState() 方法中调用getDoctors() 一次,存储Future 并将其传递给FutureBuilder,从而确保它是只做一次。

Future _doctorsFuture;

initState() {
    ...
    _doctorsFuture = getDoctors();
}

.
.

// Somewhere in build()
    FutureBuilder(
        future: doctorsFuture,
        builder: (BuildContext context, snapshot) {
            print(snapshot);
        }
    ),

【讨论】:

  • 什么是我不想要的有状态小部件,即 initState?
【解决方案2】:

您需要从 Future 返回值以完成连接。将您的 Future 更改为如下所示:

Future<dynamic> getDoctors() async {
    var res = await http.get(globals.domain + "users/docs/");

    if (res.statusCode == 200) {
        return json.decode(utf8.decode(res.bodyBytes));
    }

    return null;
}

并将您的 FutureBuilder 更改为:

FutureBuilder(
    future: getDoctors(),
    builder: (BuildContext context, AsyncSnapshot<dynamic> snapshot) {
        print(snapshot);

        if (snapshot.connectionState == ConnectionState.done && snapshot.hasData && snapshot.data != null) {
            return Center(...);
        }

        return Center(child: CircularProgressIndicator());
    },
)

请修改以匹配您的变量和类。

【讨论】:

  • 它过渡到完成然后又回到等待,奇怪的是它正在另一个页面上工作
  • 它会定期打印快照,并且每次连接到 URL 时都会继续打印。这是否意味着定期调用未来函数?
  • 这将解决问题,但不是出于上述原因。
  • FIrebase 原因。设置索引
【解决方案3】:

改变Future的回报,如:

`Future<String> getDoctors() async{
     var res = await http.get(globals.domain + 'users/docs/');
     var resBody = json.decode(utf8.decode(res.bodyBytes));
     if (res.statusCode == 200) {
        if (mounted) {
           setState(() {
               doctors = resBody;
           });
        }
     }
 }`

和 FutureBuilder:

`FutureBuilder(
    future: getDoctors(),
    builder: (BuildContext context, AsyncSnapshot<dynamic> snapshot) {
       switch (snapshot.connectionState) {
          case ConnectionState.none:
            break;
          case ConnectionState.waiting:
            return CircularProgressIndicator(
                       color: Colors.black54,
                       strokeWidth: 2,
                   );
          case ConnectionState.active:
             break;
          case ConnectionState.done:
             return Container(/*here write your return code*/);
       }
    return Text('Some error ocurred try getDoctor');
  },
);`

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-03-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多