Flutter PageView 自由控制状态保持

Posted 一叶飘舟

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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方法,无法达到保存状态的要求

保持状态

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

控制组件的状态是否保持


组件内控制

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重新打印

组件外控制

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

总线

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 自由控制状态保持的主要内容,如果未能解决你的问题,请参考以下文章

flutter 基于pageview 制作上下轮播文字功能

如何在 Flutter 中创建垂直滚动的 PageView?

在垂直PageView中包装不同高度的项目 - Flutter

Flutter - 如何制作 PageView 和 ListView?

Flutter状态管理——InheritedWidget

Flutter状态管理——InheritedWidget