Reputation: 2598
Switching between tabs initstate() called multiple times.
i have 4 tabs in my tab barA,B,C and D.
case (1) if i switch in tab like from tab A to B it's working fine.
case (2) but if i'm go to tab A to C then initstate() of tab 'B' called two times
results of case (1)
flutter: A
flutter: B
results of case (2)
flutter: A
flutter: B
flutter: C
flutter: B
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> with SingleTickerProviderStateMixin{
TabController _controller;
void initState() {
super.initState();
_controller = TabController(length: 4, vsync: this);
_controller.addListener(_handleSelected);
}
bool alarm = false;
// Function for handle tap event of tab
void _handleSelected() async {
}
Widget build(BuildContext context) {
return DefaultTabController(
length: 4,
child: Scaffold(
appBar: AppBar(
bottom: TabBar(
controller: _controller,
tabs: [
Tab(text: "A"),
Tab(text: "B"),
Tab(text: "C"),
Tab(text: "D"),
],
),
actions: [
Switch(
value: alarm,
onChanged: (value) {
},
activeTrackColor: Color(0xffff6b6b),
activeColor: Color(0xffff0000),
),
],
),
body: TabBarView(
controller: _controller,
children: [
A(),
B(),
C(),
D(),
],
),
),
);
}
}
Upvotes: 5
Views: 6398
Reputation: 1061
To keep a stateful widget alive (not rebuild or re-render), you can use AutomaticKeepAliveClientMixin
. By this way, you can easily decide which widget need to rebuild by changing ``wantKeepAlive'' parameter.
Here is a example for Class A:
class A extends StatefulWidget {
@override
_AState createState() => _AState();
}
class _AState extends State<A> with AutomaticKeepAliveClientMixin{
bool _isLoading;
@override
void initState() {
super.initState();
Future.delayed(Duration(seconds: 3)).then((_){
setState(() {
_isLoading = false;
});
});
}
@override
Widget build(BuildContext context) {
return Center(
child: _isLoading == false ?
Text("A")
: CircularProgressIndicator(),
);
}
@override
bool get wantKeepAlive => true;
}
Upvotes: 3
Reputation: 1112
You can use IndexedStack
widget to solve this kind of problem.
In _MyHomePageState
use one variable to manage index of selected page;
class _MyHomePageState extends State<MyHomePage> with SingleTickerProviderStateMixin{
int _selectedPage;
/////
Your code
/////
}
In the body of your scaffold implement IndexedStack
body: IndexedStack(
index:_selectedPage,
children: [
A(),
B(),
C(),
D(),
],
),
Now in _handleSelected ()
method handle take the latest page index from controller and using setState update the tab bar
void _handleSelected () async {
int index = _controller.page ;// get index from controller (I am not sure about exact parameter name for selected index) ;
setState((){
_selectedPage = index;
});
}
Upvotes: 5