防止 ListView 重绘 Flutter 中的所有项目

Prevent ListView to redraw all items in Flutter

我使用 FutureBuilder 在我的 listView 中构建项目。 第一次调用没问题,但第二次,甚至更多,所有项目都被重新创建,而不仅仅是新闻;这会在添加新项目时产生剪裁效果。 我检查小部件是否必须在 scrollController 中进行 API 调用。 这是我的代码:

class _Page2State extends State<Page2> {
  ScrollController _scrollController = new ScrollController();
  List _pokemonLightList = [];
  String _nextUrl;

  @override
  void initState() {
    _scrollController.addListener(() {
      if (_scrollController.position.pixels ==
          _scrollController.position.maxScrollExtent) {
        setState(() {});
      }
    });
    super.initState();
  }

  @override
  void dispose() {
    _scrollController.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return new Scaffold(
        appBar: new AppBar(title: new Text("Dynamic Demo")),
        body: FutureBuilder(
            future: bloc.getPokemonLightList(_nextUrl),
            builder: (BuildContext context,
                AsyncSnapshot<PokemonLightList> snapshot) {
              if (snapshot.hasError)
                return new Text('Error: ${snapshot.error}');
              else {
                switch (snapshot.connectionState) {
                  case ConnectionState.none:
                  case ConnectionState.waiting:
                    return Center(child: CircularProgressIndicator());
                  default:
                    if (snapshot.hasData) {
                      _nextUrl = snapshot.data.next;
                      _pokemonLightList.addAll(snapshot.data.results);
                    }
                    return _buildList(_pokemonLightList);
                }
              }
            }));
  }

  Widget _buildList(List list) {
    return ListView.separated(
      key: PageStorageKey('myListView'),
      shrinkWrap: true,
      primary: false,
      //+1 for progressbar
      itemCount: list.length + 1,
      separatorBuilder: (context, index) {
        return Divider();
      },
      itemBuilder: (BuildContext context, int index) {
        if (index == list.length) {
          return Center(child: CircularProgressIndicator());
        } else {
          return Card(
            color: Colors.amberAccent,
            child: Padding(
                padding: const EdgeInsets.all(12.0),
                child: Column(
                  children: <Widget>[
                    Text(
                      (list[index].name),
                      style: TextStyle(color: Colors.black),
                    ),
                    Text(
                      (list[index].url),
                      style: TextStyle(color: Colors.black),
                    ),
                  ],
                )),
          );
        }
      },
      controller: _scrollController,
    );
  }
}

这是裁剪效果:https://ibb.co/BnGWsfr

感谢您的帮助

原因
每次发出重建时,都会调用 FutureBuilder 状态的 didUpdateWidget。此函数检查旧的 future 对象是否与新的不同,如果不同,则重新触发 FutureBuilder
您可以参考 https://github.com/flutter/flutter/issues/11426#issuecomment-414047398
中的详细信息 和 https://medium.com/saugo360/flutter-my-futurebuilder-keeps-firing-6e774830bc2

解决方案

Future _future;

    @override
  void initState() {
    _future = bloc.getPokemonLightList();

    _scrollController.addListener(() {
      if (_scrollController.position.pixels ==
          _scrollController.position.maxScrollExtent) {
        setState(() {           
           bloc.getPokemonLightList(_nextUrl);            
        });
      }
    });

    super.initState();
  }

FutureBuilder(
  future: _future,