The Context
I have a flutter application and the main screen of the application is a Scaffold with a PageView body a BottomNavigationBar with four children:
// page declaration
@override
void initState() {
super.initState();
_children = [
const Page1(),
const Page2(),
const Page3(),
const Page4(),
];
}
// body
SafeArea(
child: PageView(
physics: NeverScrollableScrollPhysics(),
controller: _pageController, // just a PageController
children: _children,
onPageChanged: _onPagechanged,
),
)
// bottom nav bar
BottomNavigationBar(
showSelectedLabels: false,
showUnselectedLabels: false,
backgroundColor: Colors.white,
type: BottomNavigationBarType.fixed,
items: [
icon1, icon2, icon3, icon4,
],
currentIndex: _selectedIndex,
onTap: _onItemTapped,
)
int _selectedIndex = 0; // starts at 0
void _onItemTapped(int index) {
_pageController.jumpToPage(index);
}
void _onPagechanged(int index) {
setState(() => _selectedIndex = index);
}
Each child page is constructed using a const constructor, is a stateful widget, and uses with AutomaticKeepAliveClientMixin and this code bit:
@override
bool get wantKeepAlive => true;
There are some stateful widgets down the tree that use an API call to load an image from the web into a Uint8List state variable. That variable is initially null, and I use the initState override to make the call and then update the variable:
@override
void initState() {
_loadImage();
super.initState();
}
Future _loadImage() async {
final resourcePath = widget.item.imageUrl;
final up = Provider.of<UserProvider>(context, listen: false);
final fbss = FirebaseStorageService(up.uid);
final image = await fbss.getResourceWithCache(resourcePath, isItem: true, saveToCache: false);
setState(() {
_image = image;
_isLoaded = true;
});
}
While the state variable is null (and the API call is running), I show a circular progress indicator; when the image is loaded and no longer null, I use the image in a container as a decoration image for a BoxDecoration widget. The color of the BoxDecoration widget is Colors.grey.
The Problem
Whenever I navigate away from one screen to the next, and then go back, those widgets that are making API calls and loading images flash grey, and then the image is painted back onto the widget. Why is that? Is there a way I should be loading it to make it so that doesn’t happen? I’m aware that whenever I change the screen I’m looking at the widget that holds the scaffold with the bottom nav bar rebuilds because of a state change, but why does that make the images appear to be rebuilding? I’ve verified that those widgets with the images don’t in fact rebuild, but it looks like they do. I’d like to prevent this behavior. Do I need to use routes and a Navigator with my pages? What will help to prevent the appearance of reloading every time a users switches between screens?
If you need more context/code, please ask in a comment and I’ll be quick to answer.




