首页 > 解决方案 > 即使 itemCount 是恒定的,ListView 以及构建器内的 http 请求也会不断刷新

问题描述

在代码片段中 -

http请求会永远运行,ListView结果也会永远更新。

1 - 据我了解,它不应该只运行 5 次itemCount吗?

2 - 为列表的不同项目生成不同的http请求而不事先将其存储在列表中的更好方法是什么?(有点像缓存的图像)

////
        ListView.separated(
                  separatorBuilder: (context, int) => Divider(),
                  itemCount: 5,
                  itemBuilder: (context, index) {
                http.get('http://icanhazdadjoke.com',
                    headers: {'Accept': 'text/plain'}).then((value) async {
                  var s =value;

              setState(() {
                joke = s.body;
              });

            });

            return ListTile(
              title: Text(index.toString()),
              subtitle: Text(joke),
            );
          },
        ),
////

标签: flutter

解决方案


第一次,当小部件构建时,它会触发get调用。

每次get调用得到响应时,then您都在调用setState. 调用 set state 将再次重建小部件。这将导致get再次触发呼叫。

您只能get拨打一次电话initState

import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;

void main() {
  runApp(
    MaterialApp(
      home: MainPage(),
      debugShowCheckedModeBanner: false,
    ),
  );
}

class MainPage extends StatefulWidget {
  @override
  _MainPageState createState() => _MainPageState();
}

class _MainPageState extends State<MainPage> {
  Future<String> joke;

  @override
  void initState() {
    joke = _httpGetRequest();
    super.initState();
  }

  Future<String> _httpGetRequest() async {
    http.Response response = await http.get(
      'http://icanhazdadjoke.com',
      headers: {'Accept': 'text/plain'},
    );
    return response.body;
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text("Demo")),
      body: FutureBuilder(
        future: joke,
        builder: (context, snapshot) {
          if (snapshot.connectionState == ConnectionState.waiting)
            return Center(
              child: CircularProgressIndicator(),
            );
          else if (snapshot.hasError)
            return Center(
              child: Text(snapshot.error.toString()),
            );
          else
            return ListView.separated(
              separatorBuilder: (context, int) => Divider(),
              itemCount: 5,
              itemBuilder: (context, index) {
                return ListTile(
                  title: Text(index.toString()),
                  subtitle: Text(snapshot.data ?? "null"),
                );
              },
            );
        },
      ),
    );
  }
}

推荐阅读