Flutter PageView 自由控制状态保持

这里写自定义目录标题

  • 需求
  • 创建页面
    • 保持状态
    • 控制组件的状态是否保持
      • 组件内控制
      • 组件外控制

需求

tabBottom页在切换时保持状态(keepalive),但在某些特殊情况下可以使其不保存状态以达到刷新效果
例如:购物车。正常使用购物车,需要保持页面状态,但在新的商品加入购物车后,需要重新获取购物车列表

创建页面

首页

import 'package:flutter/material.dart';

class Home extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    print('home build');
    return Scaffold(
      body: Center(child: Text('首页'),),
    );
  }
}

购物车页

import 'package:flutter/material.dart';

class ShoppingCart extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    print('ShoppingCart build');
    return Scaffold(
      body: Center(child: Text('购物车页'),),
    );
  }
}

tabBottom页

import 'package:flutter/material.dart';
import 'package:learn/pages/home.dart';
import 'package:learn/pages/shoppingCart.dart';

class TabBottom extends StatefulWidget {
  @override
  _TabBottomState createState() => _TabBottomState();
}

class _TabBottomState extends State<TabBottom> {

  //页面列表
  List pages = [
    Home(),
    ShoppingCart(),
  ];
  //页面控制器
  PageController _pageController = PageController();
  //当前页面index,监听
  ValueNotifier<int> _selectIndex = ValueNotifier(0);


  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: PageView.builder(
        controller: _pageController,
        onPageChanged: (index){
          _selectIndex.value = index;
        },
        itemBuilder: (ctx,index){
          return pages[index];
        }
      ),
      bottomNavigationBar: ValueListenableBuilder(
        valueListenable: _selectIndex,
        builder: (context,value,child){
          return BottomNavigationBar(
            type: BottomNavigationBarType.fixed,
            items: [
              BottomNavigationBarItem(icon: Icon(Icons.home),label: '首页'),
              BottomNavigationBarItem(icon: Icon(Icons.shopping_cart),label: '购物车'),
            ],
            selectedItemColor: Colors.blue,
            unselectedItemColor: Color(0xff666666),
            backgroundColor: Colors.white,
            currentIndex: value,
            onTap: (index){
              _pageController.jumpToPage(index);
            },
          );
        },
      ),
    );
  }
}

效果
每次点击切换页面,都会触发build方法,无法达到保存状态的要求
Flutter PageView 自由控制状态保持_第1张图片

保持状态

1.在购物车页混入AutomaticKeepAliveClientMixin(要使用StatefulWidget,且在State中混入)
2.重写wantKeepAlive 并返回true
3.build中添加super.build(context);

import 'package:flutter/material.dart';

class ShoppingCart extends StatefulWidget {
  @override
  _ShoppingCartState createState() => _ShoppingCartState();
}

class _ShoppingCartState extends State<ShoppingCart> with AutomaticKeepAliveClientMixin {
  @override
  Widget build(BuildContext context) {
    super.build(context);

    print('ShoppingCart build');
    return Scaffold(
      body: Center(child: Text('购物车页'),),
    );
  }

  @override
  bool get wantKeepAlive => true;
}

效果
购物车页只会build一次,后续切换不会再执行build
Flutter PageView 自由控制状态保持_第2张图片

控制组件的状态是否保持

组件内控制

1.创建布尔变量 _wantKeepAlive
2.将_wantKeepAlive赋值给重写的wantKeepAlive
3.触发修改_wantKeepAlive的方法,并调用updateKeepAlive(重点,必须调用,否则无效)
购物车

import 'package:flutter/material.dart';

class ShoppingCart extends StatefulWidget {
  @override
  _ShoppingCartState createState() => _ShoppingCartState();
}

class _ShoppingCartState extends State<ShoppingCart> with AutomaticKeepAliveClientMixin {

  bool _wantKeepAlive = true;

  @override
  Widget build(BuildContext context) {
    super.build(context);

    print('ShoppingCart build');
    return Scaffold(
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Text('购物车页'),
            TextButton(onPressed: (){ _wantKeepAlive = false; this.updateKeepAlive(); }, child: Text('取消保持状态'))
          ],
        ),
      ),
    );
  }

  @override
  bool get wantKeepAlive => _wantKeepAlive;
}


效果
点击按钮后,购物车页的build重新打印
Flutter PageView 自由控制状态保持_第3张图片

组件外控制

方法有很多,推荐使用事件总线
总线

import 'package:event_bus/event_bus.dart';

EventBus eventBus = EventBus();

class ShoppingCarStateEvent{

  bool wantKeepAlive;
  ShoppingCarStateEvent({ bool wantKeepAlive = true, }){
    this.wantKeepAlive = wantKeepAlive;
  }

}

首页

import 'package:flutter/material.dart';
import 'package:learn/utils/event.dart';

class Home extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    print('home build');
    return Scaffold(
      body: Center(child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: [
          Text('首页'),
          TextButton(onPressed: (){ eventBus.fire(ShoppingCarStateEvent(wantKeepAlive: false)); }, child: Text('取消购物车保持状态')),
        ],
      )),
    );
  }
}

购物车

import 'package:flutter/material.dart';
import 'package:learn/utils/event.dart';

class ShoppingCart extends StatefulWidget {
  @override
  _ShoppingCartState createState() => _ShoppingCartState();
}

class _ShoppingCartState extends State<ShoppingCart> with AutomaticKeepAliveClientMixin {

  bool _wantKeepAlive = true;
  var _actionEventBus;

  @override
  void initState() {
    //监听
    _actionEventBus = eventBus.on<ShoppingCarStateEvent>().listen((event) {
      print('wantKeepAlive状态变化:${event.wantKeepAlive}');
      _wantKeepAlive = false;
      this.updateKeepAlive();
    });
    super.initState();
  }

  @override
  void dispose() {
    _actionEventBus.cancel();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    super.build(context);

    print('ShoppingCart build');
    return Scaffold(
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Text('购物车页'),
            TextButton(onPressed: (){ _wantKeepAlive = false; this.updateKeepAlive(); }, child: Text('取消保持状态'))
          ],
        ),
      ),
    );
  }

  @override
  bool get wantKeepAlive => _wantKeepAlive;
}


效果
第一次切换购物车页面后,不在触发build,点击首页的按钮后,在进入购物车页面,会又触发build
Flutter PageView 自由控制状态保持_第4张图片

你可能感兴趣的:(flutter,状态,flutter)