Maintaining the Flutter app state with a different approach
While developing an application, it is a major concern how our application would perform when we use Tabs or Bottom Navigation Bar kind of Widgets (Almost everything in Flutter is a widget).
As for a sample example, let's consider we have three Tabs
Users
Tab2
Tab3
on the BottomNavBar, and on the very 1st index, we are having an API call request which gets us, Fake users. In addition, the 2nd and 3rd indexes would be having ListViews respectively.
Here comes the major concern, if I switch between these indexes, the pages would load every time.
To get rid of this issue, we will be using PageView() widget, on our main screen, which does have a Bottom Navigation Bar in it.
What’s in PageView()
PageController
Physics
Children
PageController: Receives index
Physics: Whether to allow switching between the tabs or handle it manually
Children: List of Widgets
Implementation of PageView() and parameters
Pic#1
Code View
Snippet #1
import 'package:flutter/material.dart';
import 'package:maintaining_states_flutter_concept/Screens/tab_three.dart';
import 'package:maintaining_states_flutter_concept/Screens/tab_two.dart';
import 'package:maintaining_states_flutter_concept/Screens/users.dart';
class MainOne extends StatefulWidget {
const MainOne({Key? key}) : super(key: key);
@override
State<MainOne> createState() => _MainOneState();
}
class _MainOneState extends State<MainOne> {
PageController? pageController;
int? index;
List<Widget>? widgets;
@override
void initState() {
super.initState();
index = 0;
widgets = [
const Users(),
const TabTwo(),
const TabThree(),
];
pageController = PageController(initialPage: index!);
}
@override
void dispose() {
pageController!.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text("Maintaining States - Concept"),
),
body: PageView(
physics: const NeverScrollableScrollPhysics(),
controller: pageController,
children: widgets!,
),
bottomNavigationBar: BottomNavigationBar(
currentIndex: index!,
items: const [
BottomNavigationBarItem(icon: Icon(Icons.person),label: 'Users'),
BottomNavigationBarItem(icon: Icon(Icons.category_outlined),label: 'Tab2'),
BottomNavigationBarItem(icon: Icon(Icons.category_sharp),label: 'Tab3'),
],
type: BottomNavigationBarType.fixed,
onTap: (v) {
setState(() {
index = v;
});
},
),
);
}
}
Now its time to implement the code that will “Save the State”
As I mentioned that Bottom Bar would be having three tabs. For each tab we will implement it manually
Take TabTwo snippet for instance.
Snippet #2
import 'package:flutter/material.dart';
class TabTwo extends StatefulWidget {
const TabTwo({Key? key}) : super(key: key);
@override
State<TabTwo> createState() => _TabTwoState();
}
class _TabTwoState extends State<TabTwo> {
@override
Widget build(BuildContext context) {
return ListView.builder(
shrinkWrap: true,
itemCount: 22,
itemBuilder: (context, index) {
return const Card(
child: ListTile(
title: Text("TabTwo"),
),
);
},
);
}
}
Note: We must have Stateful Widget to implement State saving
On this line .. class _TabTwoState extends State<TabTwo>
add “with AutomaticKeepAliveClientMixin”.
AutomaticKeepAliveClientMixin: Allows the subtrees to request to be kept alive in lazy list.
Next, after “buildContext()”, add .. “super.build(context);”
Next, at the end of “buildContext()”, add
@override
// TODO: implement wantKeepAlive
bool get wantKeepAlive => true;
Do this for the other Two widgets as well and you’re good to go
After above implementation
Snippet #3
import 'package:flutter/material.dart';
class TabTwo extends StatefulWidget {
const TabTwo({Key? key}) : super(key: key);
@override
State<TabTwo> createState() => _TabTwoState();
}
class _TabTwoState extends State<TabTwo> with AutomaticKeepAliveClientMixin {
@override
Widget build(BuildContext context) {
super.build(context);
return ListView.builder(
shrinkWrap: true,
itemCount: 22,
itemBuilder: (context, index) {
return const Card(
child: ListTile(
title: Text("TabTwo"),
),
);
},
);
}
@override
// TODO: implement wantKeepAlive
bool get wantKeepAlive => true;
}
After running the app, you will see the magic.
So, this concludes the article.
I hope you have enjoyed reading this one.
Please clap 👏 this one if you think you have learned something new today!