In flutter, you should not make singletons. Instead, you should store it into a widget that exposes these data to all of its descendants.
Usually InheritedWidget
The reason being, with such architecture all the descendants are automatically aware of any change made to your "singleton".
A typical example would be the following:
@immutable
class User {
final String name;
User({this.name});
}
class Authentificator extends StatefulWidget {
static User currentUser(BuildContext context) {
final _AuthentificatorScope scope = context.inheritFromWidgetOfExactType(_AuthentificatorScope);
return scope.user;
}
final Widget child;
Authentificator({this.child, Key key}): super(key: key);
@override
_AuthentificatorState createState() => _AuthentificatorState();
}
class _AuthentificatorState extends State<Authentificator> {
@override
Widget build(BuildContext context) {
return _AuthentificatorScope(
child: widget.child,
);
}
}
class _AuthentificatorScope extends InheritedWidget {
final User user;
_AuthentificatorScope({this.user, Widget child, Key key}) : super(child: child, key: key);
@override
bool updateShouldNotify(_AuthentificatorScope oldWidget) {
return user != oldWidget.user;
}
}
which you have to instantiate like this:
new MaterialApp(
title: 'Flutter Demo',
builder: (context, child) {
return Authentificator(
child: child,
);
},
home: Home(),
);
and then use inside your pages like this:
@override
Widget build(BuildContext context) {
User user = Authentificator.currentUser(context);
...
}
Userobject that is shared near the top of your Widget tree. You could use something like scoped_model. This way you can define yourUserobject as a Model, complete with methods to perform login, wrap theScopedModel<User>around your root and useScopedModelDescendant<User>where ever you have login buttons or User name text labels.Navigator.ofis going to search up the widget hierarchy until it finds the closest NavigatorState. If you only provide navigation using the WidgetsApp or MaterialApp, then that's the widget it will find. This means that as long as you wrap your App with theScopedModel<User>then the scoped model descendants will be able to find it, even if you change routes.