在做一個(gè)美女相冊(cè)flutter demo app的時(shí)候發(fā)現(xiàn),每次切換頁(yè)面的時(shí)候,里面的子頁(yè)面(GridView widget)每次都會(huì)重新加載,就像下面這樣:
重新加載
這樣的體驗(yàn)肯定不行。經(jīng)過一番調(diào)研后發(fā)現(xiàn)竟然還需要做蠻多事情的。
先看看目前的實(shí)現(xiàn):
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,
),
);
}
},
);
}
}
這個(gè)就是包含在PageView里面的子組件,很簡(jiǎn)單,通過FutureBuilder調(diào)一個(gè)接口返回?cái)?shù)據(jù)后build一個(gè)GridView。很顯然每次切換Tab的時(shí)候,應(yīng)該是每次都進(jìn)入了_BeautyListWidgetState的build方法,導(dǎo)致每次都會(huì)重新刷新。那要怎樣才能做到加載后切換不再刷新呢?
1、_BeautyListWidgetState實(shí)現(xiàn)AutomaticKeepAliveClientMixin
需要實(shí)現(xiàn)wantKeepAlive
方法(返回true),另外在build方法最前面需要 調(diào)用super.build(context);
,如下:
class _BeautyListWidgetState extends State<BeautyListWidget> with AutomaticKeepAliveClientMixin<BeautyListWidget> {
@override
Widget build(BuildContext context) {
super.build(context); //需要調(diào)用super
return /* ... */
}
@override
bool get wantKeepAlive => true; //需要返回true
}
2、FutureBuilder中的future屬性需要是同一個(gè)實(shí)例
所以你需要在initState方法中創(chuàng)建這個(gè)Future。如下:
class _BeautyListWidgetState extends State<BeautyListWidget> with AutomaticKeepAliveClientMixin<BeautyListWidget> {
Future<List<Beauty>> _future; //保存這個(gè)實(shí)例
@override
Widget build(BuildContext context) {
super.build(context);
return FutureBuilder<List<Beauty>>(
future: _future, //每次build方法都是同一個(gè)實(shí)例
builder: (BuildContext context, AsyncSnapshot<List<Beauty>> snapshot) {
return /* ... */
}
},
);
}
@override
void initState() {
super.initState();
_future = getBeautysForTab(widget.tabIndex); //創(chuàng)建這個(gè)實(shí)例
}
@override
bool get wantKeepAlive => true;
}
好了。效果實(shí)現(xiàn)了。不過稍后還需要看看AutomaticKeepAliveClientMixin源碼,看看它是如何做到的。
保持狀態(tài)