I am building a flutter app and using Bloc and Firebase,
i am trying to access user data after signing in through get user function but i couldn’t do it,
here is my user repository implementation:
class FirebaseUserRepo implements UserRepository {
final FirebaseAuth _firebaseAuth;
final userCollection = FirebaseFirestore.instance.collection('users');
static MyUser myUserObject = MyUser.empty;
FirebaseUserRepo({FirebaseAuth? firebaseAuth})
: _firebaseAuth = firebaseAuth ?? FirebaseAuth.instance;
@override
// TODO: implement user
Stream<User?> get user {
return _firebaseAuth.authStateChanges().map((firebaseUser) {
return firebaseUser;
});
}
@override
Future<void> signIn(String email, String password) async {
try {
await _firebaseAuth.signInWithEmailAndPassword(
email: email, password: password);
getUser();
} catch (e) {
log(e.toString());
rethrow;
}
}
@override
Future<MyUser> signUp(MyUser myUser, String password) async {
try {
UserCredential user = await _firebaseAuth.createUserWithEmailAndPassword(
email: myUser.email, password: password);
myUser = myUser.CopyWith(
userId: user.user?.uid,
);
return myUser;
} catch (e) {
log(e.toString());
rethrow;
}
}
@override
Future<void> setUserData(MyUser myUser) async {
try {
await userCollection
.doc(myUser.userId)
.set(myUser.toEntity().toDocument());
} catch (e) {
log(e.toString());
rethrow;
}
}
@override
Future<void> signOut() async {
await _firebaseAuth.signOut();
}
getUser() async {
try {
final User? user = FirebaseAuth.instance.currentUser;
final uid = user?.uid;
myUserObject = await userCollection.doc(uid).get().then(
(value) => MyUser.fromEntity(UserEntity.fromDocument(value.data())));
return userCollection.doc(uid).get().then(
(value) => MyUser.fromEntity(UserEntity.fromDocument(value.data())));
} catch (e) {
log(e.toString());
rethrow;
}
}
}
my Authentication bloc:
class AuthenticationBloc extends Bloc<AuthenticationEvent, AuthenticationState> {
final UserRepository userRepository;
late final StreamSubscription<User?> _streamSubscription;
AuthenticationBloc({required this.userRepository}) :
super(const AuthenticationState.unknown()) {
_streamSubscription = userRepository.user.listen((user) {
add(AuthenticationUserChanged(user: user));
});
on<AuthenticationUserChanged>((event, emit) {
if(event.user != null){
emit(AuthenticationState.authenticated(event.user!));
}else{
emit(AuthenticationState.unauthenticated());
}
});
}
@override
Future<void> close() {
_streamSubscription.cancel();
return super.close();
}
}
and that’s my sign in bloc:
class SignInBloc extends Bloc<SignInEvent, SignInState> {
UserRepository _userRepository;
SignInBloc({required UserRepository userRepository}) :_userRepository = userRepository, super(SignInInitial()) {
on<SignInRequired>((event, emit) async {
emit(SignInProcess());
try {
await _userRepository.signIn(event.email, event.Password);
emit(SignInSuccess());
}on FirebaseAuthException catch (e) {
emit(SignInFailure(message: e.toString()));
}catch(e){
emit(SignInFailure(message: e.toString()));
}
});
on<SignOutEvent>((event,emit) async{
await _userRepository.signOut();
});
}
}
Here is how i used these classes in the front-end:
my app view:
class MyAppView extends StatelessWidget {
const MyAppView({super.key});
@override
Widget build(BuildContext context) {
MyUser myUser = MyUser.empty;
return MaterialApp(
theme: ThemeData(
colorScheme: const ColorScheme.light(
background: Colors.white,
onBackground: Colors.black,
primary: Color(0xFF0E39C6),
onPrimary: Colors.black,
secondary: Color(0xFF0DA6C2),
onSecondary: Colors.white,
tertiary: Color(0xFFFF8D6C),
error: Colors.red,
outline: Color(0xFF424242)),
),
title: 'Kyysh',
home: BlocBuilder<AuthenticationBloc, AuthenticationState>(
builder: (context, state) {
if (state.status == AuthenticationStatus.authenticated) {
return BlocProvider<SignInBloc>(
create: (context) {
return SignInBloc(
userRepository:
context.read<AuthenticationBloc>().userRepository);
},
child: BlocProvider<MyUserBloc>(
create: (context) {
return MyUserBloc(
context.read<AuthenticationBloc>().userRepository);
},
child: BlocBuilder<MyUserBloc, MyUserState>(
builder: (context, state) {
if (state is MyUserSuccess) {
return HomeScreen(myUser: state.myUser);
} else {
return WelcomeScreen();
}
}),
),
);
} else {
return const WelcomeScreen();
}
}),
);
}
}
i want to send MyUser object to the home screen to be able to access the data but it keeps showing the welcome screen – which contains the sign in screen-
thanks in advance
Ahmed el sayed is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.