Despite the fact I get the non-null user in the FirebaseAuth listeners, my provider fails to hand it over in the app, I always get null.
My UserModel and related provider:
/// The UserModel
class UserModel {
final String uid;
final String email;
final String? displayName;
UserModel({
required this.uid,
required this.email,
this.displayName,
});
}
/// The user provider
class UserProvider extends ChangeNotifier {
UserModel? _user;
UserModel? get user => _user;
/// Update user with Firebase user
void updateUser(User? firebaseUser) {
if (firebaseUser != null) {
_user = UserModel(
uid: firebaseUser.uid,
email: firebaseUser.email!,
displayName: firebaseUser.displayName,
// ... map other user properties
);
} else {
_user = null;
}
notifyListeners();
}
}
My main wires the listeners which update the user provider:
Future<void> main() async {
final _userProvider = UserProvider();
WidgetsFlutterBinding.ensureInitialized()
.renderView
.automaticSystemUiAdjustment = false;
// === Initialize Firebase
final app = await Firebase.initializeApp(
options: DefaultFirebaseOptions.currentPlatform,
);
// == Auth
FirebaseAuth.instance.authStateChanges().listen((user) {
if (user == null) {
debugPrint('User is currently signed out!');
} else {
debugPrint('User is signed in!');
}
_userProvider.updateUser(user); // I get non-null user
});
return runApp(
RootRestorationScope(
restorationId: 'root',
child: MultiProvider(
providers: [
// == The user povider
// ChangeNotifierProvider<UserProvider>(
// create: (context) => _userProvider),
ChangeNotifierProvider<UserProvider>.value(value: _userProvider),
],
child: MyApp(),
),
),
);
}
The consumer that gets null user:
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
// final user = Provider.of<UserModel?>(context); //<<= Either this line
return Consumer<UserModel?>(
builder: (context, user, child) { // <<= or this one
return Text("$user"); // return null
});
}
}
Despite the fact I get the non-null user in the FirebaseAuth listeners, my provider fails to hand it over in the app, I always get null.
My UserModel and related provider:
/// The UserModel
class UserModel {
final String uid;
final String email;
final String? displayName;
UserModel({
required this.uid,
required this.email,
this.displayName,
});
}
/// The user provider
class UserProvider extends ChangeNotifier {
UserModel? _user;
UserModel? get user => _user;
/// Update user with Firebase user
void updateUser(User? firebaseUser) {
if (firebaseUser != null) {
_user = UserModel(
uid: firebaseUser.uid,
email: firebaseUser.email!,
displayName: firebaseUser.displayName,
// ... map other user properties
);
} else {
_user = null;
}
notifyListeners();
}
}
My main wires the listeners which update the user provider:
Future<void> main() async {
final _userProvider = UserProvider();
WidgetsFlutterBinding.ensureInitialized()
.renderView
.automaticSystemUiAdjustment = false;
// === Initialize Firebase
final app = await Firebase.initializeApp(
options: DefaultFirebaseOptions.currentPlatform,
);
// == Auth
FirebaseAuth.instance.authStateChanges().listen((user) {
if (user == null) {
debugPrint('User is currently signed out!');
} else {
debugPrint('User is signed in!');
}
_userProvider.updateUser(user); // I get non-null user
});
return runApp(
RootRestorationScope(
restorationId: 'root',
child: MultiProvider(
providers: [
// == The user povider
// ChangeNotifierProvider<UserProvider>(
// create: (context) => _userProvider),
ChangeNotifierProvider<UserProvider>.value(value: _userProvider),
],
child: MyApp(),
),
),
);
}
The consumer that gets null user:
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
// final user = Provider.of<UserModel?>(context); //<<= Either this line
return Consumer<UserModel?>(
builder: (context, user, child) { // <<= or this one
return Text("$user"); // return null
});
}
}
My bad, I screwed up with my refactor and the name of the user model to use with the provider.
The consumer has to be called on UserProvider class (not UserModel) as follows:
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Consumer<UserProvider?>(
builder: (context, user, _) {
return Text("$user");
});
}
}
And, the best, is to address the model name to avoid the issue, as follows:
/// The user model
class UserModel extends ChangeNotifier {
User? _user;
User? get user => _user;
/// Update user with Firebase user
void updateUser(User? firebaseUser) {
if (firebaseUser != null) {
_user = firebaseUser;
} else {
_user = null;
}
notifyListeners();
}
}
Future<void> main() async {
final _userModel = UserModel();
WidgetsFlutterBinding.ensureInitialized()
.renderView
.automaticSystemUiAdjustment = false;
// === Initialize Firebase
final app = await Firebase.initializeApp(
options: DefaultFirebaseOptions.currentPlatform,
);
// == Auth
FirebaseAuth.instance.authStateChanges().listen((user) {
if (user == null) {
debugPrint('User is currently signed out!');
} else {
debugPrint('User is signed in!');
}
_userModel.updateUser(user);
});
return runApp(
RootRestorationScope(
restorationId: 'root',
child: MultiProvider(
providers: [
// == The user provider
ChangeNotifierProvider<UserModel>.value(value: _userModel),
],
child: MyApp(),
),
),
);
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Consumer<UserModel?>(
builder: (context, user, _) {
return Text("$user");
});
}
}