Flutter底部tab切換保持頁面狀態(tài)的2種方法(轉(zhuǎn))

我在開發(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

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容