Dart’s StreamController and Flutter’s StreamBuilder are powerful tools to achieve a better design and intra-app communication.
“The Scaffold widget takes a number of different widgets as named arguments, each of which are placed in the Scaffold layout in the appropriate place.”
The most significant among those named arguments are
Navigating between screens using Scaffold’s bottomNavigationBar can be achieved in many different ways. Most common way is
A slightly better approach can be using a combination of
So, how can it be achieved?
Let’s create a BLoC. This BLoC holds
Lets go over each piece of BLoC in detail…
by listing out the Bottom NavBar Items as enum fields it’s easy to read the code and we can take advantage of enum indexes.
Note: By default, Dart StreamController’s Stream is not a broadcast type stream. We can create one by calling broadcast() as shown in the screen print.
We need a broadcast type stream because, both body and bottomNavigationBar sections of the Scaffold listen-on the same stream to switch view based on current NavBarItem tapped.
Now, we need to set a default NavBarItem to show the default screen and NavBarItem selected. Let’s just set HOME as default.
This function holds the index tracking logic inside the BLoC separate from UI. This gets called out by onTap() when any BottomNavigationBarItem is tapped and receives the index of the tapped BottomNavigationBarItem.
Because navBarController is a private field inside the BLoC we need a handy method to close the stream from outside of the BLoC.
But, closing the Dart Stream when not needed is a best practice. This can be achieved by calling BLoC’s close() method inside State’s dispose() lifecycle method. So, we need a StatefulWidget here.
State’s lifecycle methods initState() creates the BLoC and dispose() closes the stream when not needed.
StreamBuilder in body section listens to BLoC’s stream and based on the NavBarItem enum in the current snapshot, it switches to corresponding view. Initial snapshot has the default NavBarItem (NavBarItem.HOME) and body will show homeArea().
This StreamBuilder listens to same stream but builds the BottomNavigationBar and highlights the BottomNavigationBarItem based on the NavBarItem enum in current snapshot of the stream. So, initial snapshot has default NavBarItem (HOME) and Home BarItem gets highlighted.
onTap: Calls the BLoC’s pickItem() function and supplies selected BarItem’s index value on tap. BLoC’s pickItem() feeds-in the stream with a NavBarItem enum based on the index it receives. This triggers the whole action.
Full source code is here…
I am sure there are many different ways of doing it. But, the above approach is certainly one clean way to separate the logic from UI. Dart’s StreamController and Flutter’s StreamBuilder are powerful tools to achieve a better design and intra-app communication. I hope this article is useful.