Flutter:当父状态更改时,子 Widget 会丢失状态
Flutter: Child Widget's looses state when parent's sate changes
我正在学习 Flutter 并正在努力解决一些状态管理问题。
我有一个 HomeScreen 小部件,其中包含 Scaffold 和 BottomNavigationBar。要根据 BottomNavigationBar 中的选定选项卡切换页面,我将 PageView 与 PageController 结合使用。以下是 HomeScreen 小部件的 build
方法的外观:
@override
Widget build(BuildContext context) {
return Scaffold(
extendBodyBehindAppBar: _currentIndex == 2,
appBar: AppBar(...properties),
body: PageView(
controller: _pageController,
children: _pages,
),
bottomNavigationBar: BottomNavigationBar(
items: const <BottomNavigationBarItem>[...items],
currentIndex: _currentIndex,
onTap: _onItemTapped, //This changes state _currentIndex and calls the method _pageController.jumpToPage(_currentIndex);
),
);
}
_currentIndex
最初是 0.
_pages
是一个包含 3 个小部件的列表。
_pageController
是初始页面设置为 0 的简单 PageController。
如果您注意到我正在使用 属性 extendBodyBehindAppBar: _currentIndex == 2
,它正在使用 _currentIndex
状态,这会导致问题。
当我点击 BottomNavigationBar 上的最后一个选项卡时,状态 _currentIndex
更改为 2,因此 extendBodyBehindAppBar
设置为 true
这使得整个脚手架自行重建并且 PageView 的状态是迷路了。
如果注释掉 extendBodyBehindAppBar: _currentIndex == 2
行,那么即使脚手架重建,PageView 小部件的状态也会保留。
据我了解,Flutter 应该保持子 Widget 的状态,即使父 Widget 重建也是如此,因为 WidgetTree 没有更改或重新排列。我尝试在 PageView 上使用 Key 但没有任何效果。
非常感谢任何帮助。
参考Lucas Salton Cardinali post on medium
你需要使用 PageStorage 来保持你需要的 child 在被销毁后的状态。
这里是从同一页面检索到的示例:
import 'package:flutter/material.dart';
// ...
void main() => runApp(MyApp());
// ...
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
final List<Widget> pages = <Widget>[
ColorBoxPage(
key: PageStorageKey('pageOne'),
),
ColorBoxPage(
key: PageStorageKey('pageTwo'),
)
];
int currentTab = 0;
final PageStorageBucket _bucket = PageStorageBucket();
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Persistence Example"),
),
body: PageStorage(
child: pages[currentTab],
bucket: _bucket,
),
bottomNavigationBar: BottomNavigationBar(
currentIndex: currentTab,
onTap: (int index) {
setState(() {
currentTab = index;
});
},
items: <BottomNavigationBarItem>[
BottomNavigationBarItem(
icon: Icon(Icons.home),
label: 'page 1',
),
BottomNavigationBarItem(
icon: Icon(Icons.settings),
label: 'page2',
),
],
),
);
}
}
class ColorBoxPage extends StatelessWidget {
ColorBoxPage({
Key? key,
}) : super(key: key);
@override
Widget build(BuildContext context) {
return ListView.builder(
itemExtent: 250.0,
itemBuilder: (context, index) => Container(
padding: EdgeInsets.all(10.0),
child: Material(
color: index % 2 == 0 ? Colors.cyan : Colors.deepOrange,
child: Center(
child: Text(index.toString()),
),
),
),
);
}
}
我正在学习 Flutter 并正在努力解决一些状态管理问题。
我有一个 HomeScreen 小部件,其中包含 Scaffold 和 BottomNavigationBar。要根据 BottomNavigationBar 中的选定选项卡切换页面,我将 PageView 与 PageController 结合使用。以下是 HomeScreen 小部件的 build
方法的外观:
@override
Widget build(BuildContext context) {
return Scaffold(
extendBodyBehindAppBar: _currentIndex == 2,
appBar: AppBar(...properties),
body: PageView(
controller: _pageController,
children: _pages,
),
bottomNavigationBar: BottomNavigationBar(
items: const <BottomNavigationBarItem>[...items],
currentIndex: _currentIndex,
onTap: _onItemTapped, //This changes state _currentIndex and calls the method _pageController.jumpToPage(_currentIndex);
),
);
}
_currentIndex
最初是 0._pages
是一个包含 3 个小部件的列表。_pageController
是初始页面设置为 0 的简单 PageController。
如果您注意到我正在使用 属性 extendBodyBehindAppBar: _currentIndex == 2
,它正在使用 _currentIndex
状态,这会导致问题。
当我点击 BottomNavigationBar 上的最后一个选项卡时,状态 _currentIndex
更改为 2,因此 extendBodyBehindAppBar
设置为 true
这使得整个脚手架自行重建并且 PageView 的状态是迷路了。
如果注释掉 extendBodyBehindAppBar: _currentIndex == 2
行,那么即使脚手架重建,PageView 小部件的状态也会保留。
据我了解,Flutter 应该保持子 Widget 的状态,即使父 Widget 重建也是如此,因为 WidgetTree 没有更改或重新排列。我尝试在 PageView 上使用 Key 但没有任何效果。
非常感谢任何帮助。
参考Lucas Salton Cardinali post on medium 你需要使用 PageStorage 来保持你需要的 child 在被销毁后的状态。
这里是从同一页面检索到的示例:
import 'package:flutter/material.dart';
// ...
void main() => runApp(MyApp());
// ...
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
final List<Widget> pages = <Widget>[
ColorBoxPage(
key: PageStorageKey('pageOne'),
),
ColorBoxPage(
key: PageStorageKey('pageTwo'),
)
];
int currentTab = 0;
final PageStorageBucket _bucket = PageStorageBucket();
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Persistence Example"),
),
body: PageStorage(
child: pages[currentTab],
bucket: _bucket,
),
bottomNavigationBar: BottomNavigationBar(
currentIndex: currentTab,
onTap: (int index) {
setState(() {
currentTab = index;
});
},
items: <BottomNavigationBarItem>[
BottomNavigationBarItem(
icon: Icon(Icons.home),
label: 'page 1',
),
BottomNavigationBarItem(
icon: Icon(Icons.settings),
label: 'page2',
),
],
),
);
}
}
class ColorBoxPage extends StatelessWidget {
ColorBoxPage({
Key? key,
}) : super(key: key);
@override
Widget build(BuildContext context) {
return ListView.builder(
itemExtent: 250.0,
itemBuilder: (context, index) => Container(
padding: EdgeInsets.all(10.0),
child: Material(
color: index % 2 == 0 ? Colors.cyan : Colors.deepOrange,
child: Center(
child: Text(index.toString()),
),
),
),
);
}
}