下面的代码几乎是从官方flutter GitHub底部导航栏示例中复制粘贴而来的。问题是,在打开包含视图的小部件时,所有内容都是预先加载的。每次我按下底部导航栏元素时,都会重新加载所有视图。换句话说,当我按下第一个元素时,日志显示其他人(第二个和第三个)正在进行网络呼叫。当我按第二个时,日志显示第一个也在打网络电话。调试时,我发现每次从底部栏中选择一个小部件时,包含该小部件的小部件都会重新构建(有一个对方法build的调用)。
class MainScreen extends StatefulWidget{
@override
State<StatefulWidget> createState()=> MainScreenState();
}
class MainScreenState extends State<MainScreen> with TickerProviderStateMixin{
GlobalKey<ScaffoldState> scaffoldState = new GlobalKey();
int _currentSelection = 0;
BottomNavigationBarType _navigationBarType = BottomNavigationBarType.fixed;
Li
st<NavigationIconView> _navigationIcons;
@override
void initState() {
super.initState();
_navigationIcons = <NavigationIconView>[
new NavigationIconView(
icon: const Icon(Icons.home),
title: 'Главная',
vsync: this
),
new NavigationIconView(
icon: const Icon(Icons.map),
title: 'Квесты',
vsync: this
),
new NavigationIconView(
icon: const Icon(Icons.dehaze),
title: 'Профиль',
vsync: this
)
];
for(NavigationIconView v in _navigationIcons)
v.controller.addListener(_rebuild);
_navigationIcons[_currentSelection].controller.value = 1.0;
}
@override
void dispose() {
for(NavigationIconView v in _navigationIcons)
v.controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
final BottomNavigationBar botNavBar = new BottomNavigationBar(
items: _navigationIcons
.map((NavigationIconView navigationView) => navigationView.item)
.toList(),
currentIndex: _currentSelection,
fixedColor: Colors.green,
type: _navigationBarType,
onTap: (int index) {
setState(() {
_navigationIcons[_currentSelection].controller.reverse();
_currentSelection = index;
_navigationIcons[_currentSelection].controller.forward();
print('pressed : $_currentSelection');
});
},
);
return new Scaffold(
key: scaffoldState,
body: new Center(
key: new Key('Main view container'),
child: new FutureBuilder<Widget>(
future: _buildTransitionsStack(),
builder: (BuildContext context, AsyncSnapshot<Widget> snapshot){
if(!snapshot.hasError) return snapshot.data;
else{
print('sh3t happened in main : ${snapshot.error}');
}
}
),
),
bottomNavigationBar: botNavBar,
);
}
Future<Widget> _buildTransitionsStack() {
final List<FadeTransition> transitions = <FadeTransition>[];
return _showMain().then((mainWidget){
transitions.add(_navigationIcons[0]
.transition(_navigationBarType,mainWidget, context));
print('size ${transitions.length}');
}).then((_){
transitions.add(_navigationIcons[1].transition(_navigationBarType,
_showQuest(), context));
transitions.add(_navigationIcons[2].transition(_navigationBarType,
_showProfile(), context));
transitions.sort((FadeTransition a, FadeTransition b) {
final Animation<double> aAnimation = a.opacity;
final Animation<double> bAnimation = b.opacity;
final double aValue = aAnimation.value;
final double bValue = bAnimation.value;
return aValue.compareTo(bValue);
});
return new Stack(children: transitions);
});
}
Future<Widget> _showMain(){
return _getToken().then((token){
return new FeedView(token);
});
}
Widget _showQuest(){
// return DetailableListScreen(ViewModelType.QUEST);
return new QuestScreen();
}
Widget _showProfile(){
return new Text('profile');
// TODO
}
void _rebuild() {
setState(() {
});
}
Future<String> _getToken() async{
return await SharedPreferences.getInstance()
.then((SharedPreferences sp)=> sp.getString(TOKEN)
);
}
}}
4条答案
按热度按时间dxpyg8gm1#
切换选项卡时保持页面活动的解决方案是将页面 Package 在IndexedStack中。
mnemlml82#
我绝对推荐观看**@amrnt**视频。但是对于那些想要直接答案的人,您需要为底部栏部分的每个页面示例化一个PageStorageKey,然后通过构造函数使每个页面接收其PageStorageKey。
7vhp5slm3#
更好的方法是使用IndexedStack,而不是PageStorage或AutomaticKeepAliveClientMixin。
IndexedStack Widget是Stack Widget的子类别。它会显示所提供查尔兹清单中的单一子系。它的大小与最大子系一样大。它会保留所有子系的状态。
oyjwcjzk4#
使用PageStorageKey存储数据,并在以后检索数据以保存内存。PageStorageKey最适合用于bottomNavigationBar中的更多选项卡的高效内存使用。https://api.flutter.dev/flutter/widgets/PageStorageKey-class.html