我们在使用TabBar或者BottomNavigationBar的时候,都会配合使用 TabBarView和PageView 进行页面展示,但如果不做特别处理的话,我们会发现在每次切换页面之后,页面都会重新刷新(比如一个列表页面,拉到最后一条数据,然后跳转到其它Tab再跳转回来,列表又变成从第一条数据开始展示),实在是很不友好。这里有两种办法解决:
- PageStorageKey
- AutomaticKeepAliveClientMixin
两种方法都能记录页面状态,两者又有些异同:
- 两者都是在 TabBarView 和 PageView 的子页面进行设置
- 设置 PageStorageKey 的页面每次都是会重新走生命周期,也就是每次进入页面都会重新调用 initState() 和 build 等一系列方法;而设置 AutomaticKeepAliveClientMixin 的页面只在第一次进入的时候会走页面的生命周期,后面不会重新调用。
1、PageStorageKey
class TabPageTestController extends StatefulWidget {
final String title;
TabPageTestController({Key key, this.title}): super(key: key);
@override
_TabPageTestControllerState createState() => _TabPageTestControllerState();
}
class _TabPageTestControllerState extends State<TabPageTestController>{
List<String> dates = <String>[];
@override
void initState() {
super.initState();
for (var i = 1; i < 20; i++) {
dates.add('${widget.title}, item$i');//如 “页面1,item1”
}
}
@override
Widget build(BuildContext context) {
return ListView.builder(
key: PageStorageKey<String>(widget.title),//这里记录 ListView 的状态
itemCount: dates.length,
itemBuilder: (BuildContext context, int index) {
return ListTile( title: Text(dates[index]),);
},
);
}
}
2、AutomaticKeepAliveClientMixin
class TabPageTestController extends StatefulWidget {
final String title;
TabPageTestController({Key key, this.title}): super(key: key);
@override
_TabPageTestControllerState createState() => _TabPageTestControllerState();
}
// with AutomaticKeepAliveClientMixin 记录页面状态
class _TabPageTestControllerState extends State<TabPageTestController> with AutomaticKeepAliveClientMixin {
List<String> dates = <String>[];
//AutomaticKeepAliveClientMixin 需添加
@override
bool get wantKeepAlive => true;
@override
void initState() {
super.initState();
for (var i = 1; i < 20; i++) {
dates.add('${widget.title}, item$i');//如 “页面1,item1”
}
}
@override
Widget build(BuildContext context) {
super.build(context);//AutomaticKeepAliveClientMixin 之后添加,其实添不添加这句都能记录状态,最好还是添加一下
return ListView.builder(
key: PageStorageKey<String>(widget.title),
itemCount: dates.length,
itemBuilder: (BuildContext context, int index) {
return ListTile( title: Text(dates[index]),);
},
);
}
}
后续:在后面使用中,发现 NestedScrollView + TabBar + TabBarView/PageView 使用上面 AutomaticKeepAliveClientMixin 进行页面缓存也不是很友好,因为如果 TabBarView/PageView 装载的子页面有滚动视图的话(如下面代码),如果滚动其中一个子页面的列表,其它的子页面里面的列表也会同步滚动,网上有人找到原因:列表滚动同步解决。
class HomePage extends StatefulWidget {
@override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> with SingleTickerProviderStateMixin {
TabController _tabController;
@override
void initState() {
super.initState();
_tabController = TabController(length: 3, vsync: this);
}
@override
void dispose() {
super.dispose();
_tabController.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Color(0xFFF8F8F8),
appBar: AppBar( ),
body: NestedScrollView(
headerSliverBuilder: (BuildContext context, bool innerBoxIsScrolled) {
return <Widget>[
SliverAppBar(
...
bottom: TabBar(
controller: _tabController,
labelColor: Colors.redAccent,
unselectedLabelColor: Colors.black,
indicatorColor: Colors.redAccent,
tabs: [
Tab(text: "Tab1"),
Tab(text: "Tab2"),
Tab(text: "Tab3"),
]
),
)
];
},
body: TabBarView(
controller: _tabController,
children: [
TabPageTestController(title: 'Tab1',),
TabPageTestController(title: 'Tab2',),
TabPageTestController(title: 'Tab3',),
],
),
),
);
}
}
版权声明:本文为zhumj_zhumj原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。