防止 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,
我使用 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,