我在開發(fā)中發(fā)現(xiàn),當(dāng)每次切換底部tab按鈕時,對應(yīng)的頁面都會重新build,這就導(dǎo)致了頁面一直在更新,該頁面的數(shù)據(jù)也會跟著重新加載。那么如何讓頁面保持原來的狀態(tài),而不是每次都要重新加載刷新數(shù)據(jù)呢?有兩種方式。
第一種方式:采用IndexdStack
IndexdStack和Stack一樣,都是層布局控件,可以在一個控件上面放置另一個控件,但唯一不同的是,IndexdStack在同一時刻只能顯示子控件中的一個控件,通過index屬性來設(shè)置顯示的控件。
配置底部導(dǎo)航的核心代碼如下:
import 'package:flutter/material.dart';
import 'package:flutter_jdshop/pages/tabs/CategoryPage.dart';
import 'package:flutter_jdshop/pages/tabs/HomePage.dart';
import 'package:flutter_jdshop/pages/tabs/ShoppingCartPage.dart';
import 'package:flutter_jdshop/pages/tabs/UserPage.dart';
class Tabs extends StatefulWidget {
Tabs({Key key}) : super(key: key);
_TabsState createState() => _TabsState();
}
class _TabsState extends State<Tabs> {
int _currentIndex = 0;//記錄當(dāng)前選中哪個頁面
List <Widget> _pages = [HomePage(), GroupPage(), MyPage()];
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text("心力手冊")),
body: this._pages[this._currentIndex],
bottomNavigationBar: BottomNavigationBar(
fixedColor: Colors.red,//底部導(dǎo)航欄按鈕選中時的顏色
type: BottomNavigationBarType.fixed,//底部導(dǎo)航欄的適配,當(dāng)item多的時候都展示出來
currentIndex: this._currentIndex,
onTap: (index){
setState(() {
this._currentIndex = index;
});
},
items: [
BottomNavigationBarItem(icon: Icon(Icons.home), title: Text("首頁")),
BottomNavigationBarItem(icon: Icon(Icons.category), title: Text("小組")),
BottomNavigationBarItem(icon: Icon(Icons.shopping_cart), title: Text("購物車")),
BottomNavigationBarItem(icon: Icon(Icons.people), title: Text("我的"))
],
),
);
}
}
此時還是不可以保持頁面狀態(tài)的。
這里我們將body由
body: this._pages[this._currentIndex],
替換成
body: IndexedStack(
index: this._currentIndex,
children: this._pageList,),
這樣就能夠?qū)崿F(xiàn)保持頁面狀態(tài)了。
使用IndexedStack來保持頁面狀態(tài)的優(yōu)點(diǎn)就是配置簡單,但是它也有很大的缺點(diǎn):IndexedStack中管理的子頁面在一開始就全部一次性加載出來了,不管有沒有顯示出來,然后通過index屬性來確定到底顯示哪一個頁面。
第二種方式:AutomaticKeepAliveClientMixin
如果所有的頁面都需要保持頁面狀態(tài),那么就使用indexdStack;如果有些頁面需要保持頁面狀態(tài),有些頁面需要進(jìn)來就刷新,那么我們就需要使用AutomaticKeepAliveMixin這個類來單獨(dú)控制某個頁面的狀態(tài)。
AutomaticKeepAliveClientMixin相比IndexdStack,配置起來要復(fù)雜一些。
AutomaticKeepAliveClientMixin結(jié)合底部BottomNavigationBar來保持頁面狀態(tài)的時候,其配置步驟如下:
import 'package:flutter/material.dart';
import 'package:flutter_jdshop/pages/tabs/CategoryPage.dart';
import 'package:flutter_jdshop/pages/tabs/HomePage.dart';
import 'package:flutter_jdshop/pages/tabs/ShoppingCartPage.dart';
import 'package:flutter_jdshop/pages/tabs/UserPage.dart';
class Tabs extends StatefulWidget {
Tabs({Key key}) : super(key: key);
_TabsState createState() => _TabsState();
}
class _TabsState extends State<Tabs> {
int _currentIndex = 0;//記錄當(dāng)前選中哪個頁面
//第1步,聲明PageController
PageController _pageController;
@override
void initState() {
super.initState();
//第2步,初始化PageController
this._pageController = PageController(initialPage: this._currentIndex);
}
List<Widget> _pages = [
HomePage(),
CategoryPage(),
ShoppingCartPage(),
UserPage()
];
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text("JDShop")),
//第3步,將body設(shè)置成PageView,并配置PageView的controller屬性
body: PageView(
controller: this._pageController,
children: this._pages,
),
bottomNavigationBar: BottomNavigationBar(
fixedColor: Colors.red,//底部導(dǎo)航欄按鈕選中時的顏色
type: BottomNavigationBarType.fixed,//底部導(dǎo)航欄的適配,當(dāng)item多的時候都展示出來
currentIndex: this._currentIndex,
onTap: (index){
setState(() {
//第4步,設(shè)置點(diǎn)擊底部Tab的時候的頁面跳轉(zhuǎn)
this._currentIndex = index;
this._pageController.jumpToPage(this._currentIndex);
});
},
items: [
BottomNavigationBarItem(icon: Icon(Icons.home), title: Text("首頁")),
BottomNavigationBarItem(icon: Icon(Icons.category), title: Text("分類")),
BottomNavigationBarItem(icon: Icon(Icons.shopping_cart), title: Text("購物車")),
BottomNavigationBarItem(icon: Icon(Icons.people), title: Text("我的"))
],
),
);
}
}
以上前4步都是在tabs.dart中進(jìn)行配置的,此時所有的頁面還是不可保持頁面狀態(tài)的。然后第5步就是在需要保持頁面狀態(tài)的頁面里面混入AutomaticKeepAliveClientMixin類,并將wantKeepAlive方法返回為true,如下所示:
//首頁頁面
class _HomePageState extends State<HomePage> with AutomaticKeepAliveClientMixin{
@override
bool get wantKeepAlive => true;
//分類頁面
class _CategoryPageState extends State<CategoryPage> with AutomaticKeepAliveClientMixin{
@override
bool get wantKeepAlive => true;
這樣,首頁頁面和分類頁面就實(shí)現(xiàn)了頁面狀態(tài)的保持,頁面數(shù)據(jù)只在首次進(jìn)入該頁面的時候進(jìn)行刷新;而其他沒有實(shí)現(xiàn)頁面保持的頁面在每次進(jìn)入該頁面的時候,數(shù)據(jù)都會刷新。
轉(zhuǎn)自 https://cloud.tencent.com/developer/article/1507094