當通過底部tabBar將頁面在“首頁”和“分類”之間進行切換的時候,每一次進入頁面的時候該頁面的數據都會重新加載。那么如何讓頁面保持原來的狀態,而不是每次都要重新加載刷新數據呢?有兩種方式。
第一種方式:采用IndexdStack
IndexdStack和Stack一樣,都是層布局控件,可以在一個控件上面放置另一個控件,但唯一不同的是,IndexdStack在同一時刻只能顯示子控件中的一個控件,通過index屬性來設置顯示的控件。
配置底部導航的核心代碼如下:
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;//記錄當前選中哪個頁面 List<Widget> _pages = [ HomePage(), CategoryPage(), ShoppingCartPage(), UserPage() ]; @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: Text("JDShop")), body: this._pages[this._currentIndex], bottomNavigationBar: BottomNavigationBar( fixedColor: Colors.red,//底部導航欄按鈕選中時的顏色 type: BottomNavigationBarType.fixed,//底部導航欄的適配,當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("我的")) ], ), ); } }
此時還是不可以保持頁面狀態的。
這里我們將body由
body: this._pages[this._currentIndex],
替換成
body: IndexedStack( index: this._currentIndex, children: this._pages, ),
這樣就能夠實現保持頁面狀態了,效果如下:
我們可以看到,此時,頁面的數據只在最開始進來的時候進行加載,然后就保持住這個頁面的狀態了,並不會每次進來都進行數據的加載刷新了。
使用IndexedStack來保持頁面狀態的優點就是配置簡單,但是它也有很大的缺點:IndexedStack中管理的子頁面在一開始就全部一次性加載出來了,不管有沒有顯示出來,然后通過index屬性來確定到底顯示哪一個頁面。
第二種方式:AutomaticKeepAliveClientMixin
如果所有的頁面都需要保持頁面狀態,那么就使用indexdStack;如果有些頁面需要保持頁面狀態,有些頁面需要進來就刷新,那么我們就需要使用AutomaticKeepAliveMixin這個類來單獨控制某個頁面的狀態。
AutomaticKeepAliveClientMixin相比IndexdStack,配置起來要復雜一些。
AutomaticKeepAliveClientMixin結合底部BottomNavigationBar來保持頁面狀態的時候,其配置步驟如下:
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;//記錄當前選中哪個頁面 //第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設置成PageView,並配置PageView的controller屬性 body: PageView( controller: this._pageController, children: this._pages, ), bottomNavigationBar: BottomNavigationBar( fixedColor: Colors.red,//底部導航欄按鈕選中時的顏色 type: BottomNavigationBarType.fixed,//底部導航欄的適配,當item多的時候都展示出來 currentIndex: this._currentIndex, onTap: (index){ setState(() { //第4步,設置點擊底部Tab的時候的頁面跳轉 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中進行配置的,此時所有的頁面還是不可保持頁面狀態的。然后第5步就是在需要保持頁面狀態的頁面里面混入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;
這樣,首頁頁面和分類頁面就實現了頁面狀態的保持,頁面數據只在首次進入該頁面的時候進行刷新;而其他沒有實現頁面保持的頁面在每次進入該頁面的時候,數據都會刷新。
使用AutomaticKeepAliveClientMixin這個類來保持首頁和分類頁面狀態。
原文地址:https://cloud.tencent.com/developer/article/1507094