android - FutureBuilder 不会等待 future 完成

标签 android flutter flutter-futurebuilder

我正在使用 API 调用来获取数据并在 ListView 中显示。

这是 future builder 类:

Widget futureBuilder() {
    return FutureBuilder<List<Project>>(
      future: _getProjects(),
      builder: (context, snapshot) {
        debugPrint('Builder');
        switch (snapshot.connectionState) {
          case ConnectionState.none:
          case ConnectionState.waiting:
          default:
            if (snapshot.hasError)
              return new Text('Error: ${snapshot.error}');
            else
              return listWidget(snapshot);
        }
      },
    );
  }
}

问题是,甚至在 _getProjects() 返回结果之前就调用了 debugPrint('Builder'),因此快照在我的 ListView Widget 中作为 null 传递。

这是 _getProjects() 类:

Future<List<Project>> _getProjects() async {
    List<Project> projects = [];
    String getProjects = "https://api.myjson.com/bins/1g3xpe";
    var response = await http.get(getProjects);
    Iterable list = json.decode(response.body);
    projects = list.map((model) => Project.fromJson(model)).toList();
    debugPrint('Size ' + projects.length.toString());
    return projects;
  }

完整代码如下:

class Projects extends StatefulWidget {
  @override
  ProjectState createState() => new ProjectState();
}

class ProjectState extends State {

   Future<List<Project>> _getProjects() async {
    List<Project> projects = [];
    String getProjects = "https://api.myjson.com/bins/1g3xpe";
    var response = await http.get(getProjects);
    Iterable list = json.decode(response.body);
    projects = list.map((model) => Project.fromJson(model)).toList();
    debugPrint('Size ' + projects.length.toString());
    return projects;
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      primary: true,
      appBar: EmptyAppBar(),
      body: Column(
        children: <Widget>[
          headerWidget(),
          futureBuilder()
        ],
      ),
    );
  }

  Widget futureBuilder() {
    return FutureBuilder<List<Project>>(
      future: _getProjects(),
      builder: (context, snapshot) {
        debugPrint('Builder');
        switch (snapshot.connectionState) {
          case ConnectionState.none:
          case ConnectionState.waiting:
          default:
            if (snapshot.hasError)
              return new Text('Error: ${snapshot.error}');
            else
              return listWidget(snapshot);
        }
      },
    );
  }
}



Widget headerWidget() {
  return Container(
    padding: EdgeInsets.all(16.0),
    color: Colors.blueAccent,
    child: Container(
        decoration: ShapeDecoration(
            color: Colors.white,
            shape: RoundedRectangleBorder(
                borderRadius: BorderRadius.all(Radius.circular(25.0)),
                side: BorderSide(color: Colors.white))),
        child: Row(
          children: <Widget>[
            Padding(padding: EdgeInsets.only(left: 12)),
            Icon(Icons.arrow_back, color: Colors.black54),
            Padding(padding: EdgeInsets.only(left: 12)),
            Flexible(
              fit: FlexFit.loose,
              child: searchBar(),
            ),
            Icon(
              Icons.search,
              color: Colors.black54,
            ),
            Padding(padding: EdgeInsets.only(right: 12)),
          ],
        )),
  );
}

Widget searchBar() {
  return Container(
    height: 52,
    alignment: Alignment.centerLeft,
    padding: EdgeInsets.only(left: 12, right: 12),
    child: TextField(
      decoration: new InputDecoration.collapsed(
        border: InputBorder.none,
        filled: false,
        hasFloatingPlaceholder: false,
        hintText: 'Search here',
        hintStyle: TextStyle(color: Colors.black54),
      ),
    ),
  );
}

Widget listWidget(AsyncSnapshot<List<Project>> snapshot) {
  return Scaffold(
      body: ListView.builder(
          itemBuilder: (BuildContext context, int index) {
            listItem(snapshot.data[index]);
          },
          itemCount: snapshot.data.length));
}

Widget listItem(Project project) {
  return Card(
    elevation: 6.0,
    child: Column(
      children: <Widget>[Text('Project ID'), Text('Project Name')],
    ),
  );
}

class EmptyAppBar extends StatelessWidget implements PreferredSizeWidget {
  @override
  Widget build(BuildContext context) {
    return Container();
  }

  @override
  Size get preferredSize => Size(0.0, 0.0);
}

更新: 我对 FutureBuilder 做了一些更改:

Widget futureBuilder() {
    return FutureBuilder<List<Project>>(
      future: _getProjects(),
      builder: (context, snapshot) {
        debugPrint('Builder');
        switch (snapshot.connectionState) {
          case ConnectionState.done:
            if (snapshot.hasError)
              return new Text('Error: ${snapshot.error}');
            else
              return listWidget(snapshot);
            break;

          default:
            debugPrint("Snapshot " + snapshot.toString());
        }
      },
    );
  }

我现在收到此错误:

I/flutter ( 4054): _FutureBuilderState<List<Project>>#67dc4):
I/flutter ( 4054): A build function returned null.
I/flutter ( 4054): The offending widget is: FutureBuilder<List<Project>>
I/flutter ( 4054): Build functions must never return null. To return an empty space that causes the building widget to
I/flutter ( 4054): fill available room, return "new Container()". To return an empty space that takes as little room as
I/flutter ( 4054): possible, return "new Container(width: 0.0, height: 0.0)".

默认情况下 SnapShot 返回此快照 AsyncSnapshot>(ConnectionState.waiting, null, null)

最佳答案

您需要检查AsyncSnapshot(快照)是否有返回数据。 添加如下 if 语句:

if(snapshot.hasData && !snapshot.hasError) {
//rest of your code
}
else {
//show progress indicator or error...
}

关于android - FutureBuilder 不会等待 future 完成,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56249715/

相关文章:

flutter - Flutter:应该只有[DropdownButton]值的一项

Flutter StreamBuilder 与 FutureBuilder

android - 如何单独在我的最后一个列表项下方获得一些空间 - android

testing - 获取小部件在 Flutter 测试中的位置?

android - 从抽屉导航布局中删除间隙

flutter - 点击其中一个 TextField 时,TextField 文本被清除

flutter Riverpod : FutureProvider family never gets resolved

android - 无法在 FutureBuilder 中滚动 ListView

java - 如何从 CardView 内的 TextView 获取文本?

android - Xamarin Android 应用程序内存使用情况