在做一个美女相册flutter demo app的时候发现,每次切换页面的时候,里面的子页面(GridView widget)每次都会重新加载,就像下面这样:
这样的体验肯定不行。经过一番调研后发现竟然还需要做蛮多事情的。
先看看目前的实现:
class BeautyListWidget extends StatefulWidget {
final int tabIndex;
const BeautyListWidget({Key key, this.tabIndex}) : super(key: key);
@override
_BeautyListWidgetState createState() => _BeautyListWidgetState();
}
class _BeautyListWidgetState extends State<BeautyListWidget> {
@override
Widget build(BuildContext context) {
return FutureBuilder<List<Beauty>>(
future: getBeautysForTab(widget.tabIndex),
builder: (BuildContext context, AsyncSnapshot<List<Beauty>> snapshot) {
var connectionState = snapshot.connectionState;
if (connectionState == ConnectionState.done && snapshot.hasData) {
var data = snapshot.data;
return GridView.builder(
gridDelegate:
SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 2, mainAxisSpacing: 10, crossAxisSpacing: 10, ),
itemBuilder: (BuildContext context, int index) {
return FadeInImage.assetNetwork(placeholder: 'assets/loading.png', image: data[index].thumbURL);
},
itemCount: data.length,
);
} else {
return Center(
child: CircularProgressIndicator(
backgroundColor: Colors.black,
),
);
}
},
);
}
}
这个就是包含在PageView里面的子组件,很简单,通过FutureBuilder调一个接口返回数据后build一个GridView。很显然每次切换Tab的时候,应该是每次都进入了_BeautyListWidgetState的build方法,导致每次都会重新刷新。那要怎样才能做到加载后切换不再刷新呢?
1、_BeautyListWidgetState实现AutomaticKeepAliveClientMixin
需要实现wantKeepAlive
方法(返回true),另外在build方法最前面需要 调用super.build(context);
,如下:
class _BeautyListWidgetState extends State<BeautyListWidget> with AutomaticKeepAliveClientMixin<BeautyListWidget> {
@override
Widget build(BuildContext context) {
super.build(context); //需要调用super
return /* ... */
}
@override
bool get wantKeepAlive => true; //需要返回true
}
2、FutureBuilder中的future属性需要是同一个实例
所以你需要在initState方法中创建这个Future。如下:
class _BeautyListWidgetState extends State<BeautyListWidget> with AutomaticKeepAliveClientMixin<BeautyListWidget> {
Future<List<Beauty>> _future; //保存这个实例
@override
Widget build(BuildContext context) {
super.build(context);
return FutureBuilder<List<Beauty>>(
future: _future, //每次build方法都是同一个实例
builder: (BuildContext context, AsyncSnapshot<List<Beauty>> snapshot) {
return /* ... */
}
},
);
}
@override
void initState() {
super.initState();
_future = getBeautysForTab(widget.tabIndex); //创建这个实例
}
@override
bool get wantKeepAlive => true;
}
好了。效果实现了。不过稍后还需要看看AutomaticKeepAliveClientMixin源码,看看它是如何做到的。