Flutter页面切换状态维持
在flutter中,使用类似于PageView进行页面切换时,如果不做处理,不会保持页面原状态。也就是从A页面切换到B页面,再从B页面切回到A页面,A页面显示都会重新加载。如果A页面加载比较耗时(例如有网络请求),就会带来不好的用户体验。如下图所示,页面已经加载过了,再次切换时还会重新加载。
最终,我们想要的效果是页面第一次加载会进行网络请求,当再次切换回到该页面时,希望维持原状态不变,效果如下图所示:
一、TabBar+TabBarView的页面切换状态维持
方法:使用AutomaticKeepAliveClientMixin
在TabBarView(也可以用PageView)每个子页面的State类实现AutomaticKeepAliveClientMixin
接口,然后在子页面的State类重写wantKeepAlive
为true即可。
注意点:State类build方法中要添加super.build(context)
;不然会出现某些页面切换没有维持原状态。
例如:
class PersonEventList extends StatefulWidget {
@override
State<StatefulWidget> createState() {
return _PersonEventListState();
}
}
class _PersonEventListState extends State<PersonEventList>
with AutomaticKeepAliveClientMixin {
//导航栏切换时保持原有状态
@override
bool get wantKeepAlive => true;
@override
Widget build(BuildContext mContext) {
super.build(context);
return ......
.............
}}
二、底部导航栏切换时维持原状态
Flutter中底部导航栏一般使用BottomAppBar或者BottomNavigationBar组件来实现,要想维持页面切换维持原状态,如下图所示,也要做一些处理:
2.1 使用IndexedStack
IndexedStack继承自Stack,它可以叠堆多个组件,并通过index来控制指定的组件显示。我们只需要用这个Widget将body中的子页面包裹就能达到目的。
class _HomeRouteState extends State<HomeRoute> {
var _position = 0;
List<Widget> _pageList = List();
_pageList.add(RepoListRoute());
_pageList.add(RepoHistoryPage());
_pageList.add(TrendRoute());
_pageList.add(PersonDetailPage());
@override
Widget build(BuildContext context) {
return Scaffold(
bottomNavigationBar: _buildBottomAppBar(),
floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked,
body: IndexedStack(
index: _position,
children: _pageList,
),
...........
2.2 使用Offstage实现
Offstage可容纳一个子组件,可更改其消失与否,当offstage属性为true时,子组件会消失。实现的原理与IndexedStack相同。
class _HomeRouteState extends State<HomeRoute> {
var _position = 0;
List<Widget> _pageList = List();
_pageList.add(RepoListRoute());
_pageList.add(RepoHistoryPage());
_pageList.add(TrendRoute());
_pageList.add(PersonDetailPage());
@override
Widget build(BuildContext context) {
return Scaffold(
bottomNavigationBar: _buildBottomAppBar(),
floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked,
body: Stack(
children: [
Offstage(
offstage: _position != 0,
child: _pageList[0],
),
Offstage(
offstage: _position != 1,
child: _pageList[1],
),
Offstage(
offstage: _position != 2,
child: _pageList[2],
),
],
),
...........
上面两种方式都能实现保持原页面状态,原理相同。但是,在第一次加载时,所有子页面都被实例化了,开销较大。所以可以采用下面第三种方式。
2.3 PageView + AutomaticKeepAliveClientMixin方式
body使用PageView来容纳所有子页面,在底部BottomAppBar的item点击时通过PageView的Controler实现页面切换,然后每个子页面继承AutomaticKeepAliveClientMixin即可。
三、项目介绍
以上例子在下面这个项目中都有体现:
项目地址:用flutter实现的一款界面精美的Github App
介绍:用Flutter实现的一款界面精美、功能较全、体验良好的Github客户端。支持多语言、换肤等功能。代码简单易懂且有充分的注释,很适用于学习Flutter。
上一篇: 线程状态及切换(三)
下一篇: 女性如何抗衰老 女性抗衰老吃五种食物
推荐阅读
-
Flutter实现页面切换后保持原页面状态的3种方法
-
Flutter实现页面切换后保持原页面状态的3种方法
-
Flutter共享FlutterEngine页面切换无法点击的问题
-
[Asp.Net Core] Blazor Server Side 项目实践 - 切换页面时保留状态
-
Flutter页面切换状态维持
-
Vue 路由 标签页切换时保留页面状态不重新加载
-
Flutter底部导航栏BottomNavigationBar页面状态保持解决方案
-
Flutter共享FlutterEngine页面切换无法点击的问题
-
[Asp.Net Core] Blazor Server Side 项目实践 - 切换页面时保留状态