颤振中的SetState

时间:2020-05-26 20:01:53

标签: flutter flutter-layout

我已经通过从API获取数据并将其放入对象列表中来动态创建了一个列表视图,但是,当我打开屏幕时(通过按下另一个屏幕上的按钮来打开屏幕),这是获取列表的唯一方法要在屏幕上显示的ListView是要进行热刷新。我曾尝试在init_state函数中设置状态,但似乎无法正常工作。

感谢您的帮助:)

class _PlanetListState extends State<PlanetList> {

List<Planet> planets = [];
String urlWeb = 'https://swapi.dev/api/planets/';

Future getData(String url) async {

    var response = await http.get(url);
    if (response.statusCode == 200) {
        var data = json.decode(response.body);

    Planet obj = Planet(
      name: data['name'],
      rotationPeriod: data['rotation_period'],
      orbitalPeriod: data['orbital_period'],
      diameter: data['diameter'],
      climate: data['climate'],
      gravity: data['gravity'],
      terrain: data['terrain'],
      population: data['population']
      );
      planets.add(obj);

      print(planets);
    }
}

@override
  void initState() {
    for (var i=0;i<62;i++){
      getData('$urlWeb$i/');
    }
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("Planets"),
        backgroundColor: Colors.amber[800],
      ),
      body: Container(
        color: Colors.black,
        child: ListView.builder(
          itemCount: planets.length,
          itemBuilder: (BuildContext context, int index){
            return Card(
              color: Colors.amber[600],
              margin:EdgeInsets.all(8),
              child: ListTile(
                leading: CircleAvatar(
                  backgroundColor: getColor(planets[index].climate),
                  backgroundImage: AssetImage('assets/planet.png'),
                ),
                contentPadding: EdgeInsets.all(5),
                title: Text('$index: ${planets[index].name}'),
                subtitle:Text(planets[index].climate),
             ),
           );
          },
        ),
      ),
    );
  }
}

1 个答案:

答案 0 :(得分:0)

正在发生的事情是,在将数据添加到列表之前,正在加载屏幕,这是因为getData函数是异步的。因此,当您的屏幕首次加载时,列表为空,并且您可能知道要在屏幕上显示更改,您必须执行setState(),这就是为什么在热刷新时会显示更改的原因。

现在您在这里有多个选择,首先您可以看一下FutureBuilder,这是一个将生成两次的小部件,一次是在您的Future解析之前,另一次是之后,这意味着“自动刷新”。在这种情况下,您的数据列表将成为Future类型,并且ListView会被FutureBuilder包装,以便在数据准备好之后构建它。

另一种选择是,每次将项目添加到拥有的对象列表中时,都执行setState()