461 字
2 分钟
请求数据保留
前言
前文中可以发现一个问题,每次切换页面,都会重新请求数据。而实际开发中,我们会对数据进行保留,在需要的时候再进行数据更新。

Mixin
调整继承关系
多继承 AutomaticKeepAliveClientMixin
class MessagePage extends StatefulWidget { @override _MessagePageState createState() => _MessagePageState();}
class _MessagePageState extends State<MessagePage> with AutomaticKeepAliveClientMixin<MessagePage> { ...}重写 wantKeepAlive
class _MessagePageState extends State<MessagePage> with AutomaticKeepAliveClientMixin<MessagePage> { ...
@override bool get wantKeepAlive => true;}调整 build 方法
@override Widget build(BuildContext context) { super.build(context); return Scaffold(...); }调整 MyHomePage (标签Tab页)
原先我们的切换Tab的逻辑是这样的:
class _MyHomePageDataSource extends State<MyHomePage> { int _selectedTab = 0; final List<Widget> _pages = [ MessagePage(), ContactsPage(), MommentPage(), MinePage() ];
@override Widget build(BuildContext context) { return Scaffold( body: _pages[_selectedTab], ... );并非所有的子页面的 widget 都在标签容器的 widget 树中,导致每次切换都会去重新生成渲染。
- 我们需要做如下调整:
- 构建
PageController - 调整
Body为PageView, 并绑定PageController和pages - 通过
PageController切换子页面
- 构建
class _MyHomePageDataSource extends State<MyHomePage> { int _selectedTab = 0; final List<Widget> _pages = [ MessagePage(), ContactsPage(), MommentPage(), MinePage() ]; // 一、 构建 PageController final PageController _pageController = PageController();
@override Widget build(BuildContext context) { return Scaffold( // 二、 调整 Body 为 PageView, 并绑定 PageController 和 pages body: PageView( controller: _pageController, children: _pages, ), bottomNavigationBar: BottomNavigationBar( selectedItemColor: Colors.green, unselectedItemColor: Colors.grey, currentIndex: _selectedTab, onTap: (idx) { setState(() { _selectedTab = idx; // 三、 通过 PageController 切换子页面 _pageController.jumpToPage(_selectedTab); }); }, items: const [...], ), ); }}检查效果

PageView
滑动切换子页面

在使用总突然发现可以通过滑动切换 PageView 的子页面。但是底部的标签选中没有变化,下面我们来处理一下。
同步标签切换
通过 onPageChanged 来监听页面的切换,同步修改选中标签。
body: PageView( onPageChanged: (idx) { setState(() { _selectedTab = idx; }); }, controller: _pageController, children: _pages, ),关闭滑动切换
当然,不需要滑动的话可以通过 physics 来进行关闭。
body: PageView( physics: const NeverScrollableScrollPhysics(), controller: _pageController, children: _pages,),