Getting the result of a method Future<T> flutter - asynchronous

I have a method
Future<FirebaseUser> getCurrentUser() async {
FirebaseUser user = await _firebaseAuth.currentUser();
return user;
}
I want to be able to call it in some other module by doing :
if (class.getCurrentUser() != null) {
// Do something
}
I cannot seem to figure out how to get the actual value, and not the Future object storing the value. In C++ for instance, I can just do future.get(), which will block and return the value to me. Is there an equivalent in flutter? I am new to the language and have searched for hours and cannot seem to find a solution to this exact problem.

From your code, it seems you actually need 1 await only:
Future<FirebaseUser> getCurrentUser() async {
return _firebaseAuth.currentUser();
}
if (await class.getCurrentUser() != null) {
// Do something
}

You have to await for the result in your method call as well like this:
FirebaseUser currentUser = await class.getCurrentUser();
if (currentUser != null) {
// Do something
}

Related

The getter 'uid' not defined

i'm trying to create a food track app on android studio, it's my first time and i'm working with firebase_auth 3.3.12. my code in the aut.dart is:
import 'package:firebase_auth/firebase_auth.dart';
import 'package:my_firstapp/models/user_model.dart';
class AuthService {
final FirebaseAuth _auth = FirebaseAuth.instance;
AuthService();
// create user object based on FirebaseUser.
UserModel _userFromUser(User) {
return user != null ? UserModel(uid: user.uid) : null;
}
// auth change user stream
Stream<UserModel> get user {
return _auth.authStateChanges()
.map(_userFromUser);
}
Future<UserModel> getUser() async {
User user = await _auth.currentUser();
return _userFromUser(user);
}
// sign in with email and password
Future signInWithEmailAndPassword(String email, String password) async {
try {
UserCredential result = await _auth.signInWithEmailAndPassword(email: email, password: password);
User user = result.user;
return _userFromUser(user);
} catch(e) {
print(e.toString());
return null;
}
}
// sign up with email and password
Future registerWithEmailAndPassword(String email, String password) async {
try {
UserCredential result = await _auth.createUserWithEmailAndPassword(email: email, password: password);
User user = result.user;
// create a new user document in database
return _userFromUser(user);
} catch(e) {
print(e.toString());
return null;
}
}
// sign out
Future signOut() async {
try {
return await _auth.signOut();
} catch(e){
print(e.toString());
return null;
}
}
}
However i'm getting 2 errors:
-The getter 'uid' isn't defined for the type 'Stream';
-The expression "await _auth.currentUser()" doesn't evaluate to a function, so it can't be invoked.
How can i rewrite the code? thanks
The _auth.currentUser is not a function (it used to be, but changed about a year ago), but rather a property. It also isn't asynchronous, so you don't need await nor to return a Future.
So:
UserModel getUser() {
User user = _auth.currentUser;
return _userFromUser(user);
}
In this code, your argument is capitalised ('User') but in the code block you write 'user'.
UserModel _userFromUser(User) {
return user != null ? UserModel(uid: user.uid) : null;
}
Furthermore, for _auth.currentUser(), you do not need to use await as it does not return a future.

FirebaseAuth throws error when I called currentUser and Observable error in rxdart

I have created an app with Google login with firestore support and recently I have updated all the dependencies to a newer version. Here There are some problem with the old code I don't know what's the problem.
Future<String> getCurrentUser() async {
var user = await _auth.currentUser();
if (user == null) {
return null;
} else {
return user.uid;
}
}
It shows error near _auth.currentUser(); and the error is The expression doesn't evaluate to a function, so it can't be invoked. I have searched for it but nothing worked. This is the First problem.
The Second problem arises with rxdart package. Due to new packages Observable is not supported and Searched it for internet and tried using Stream But they are not working.
The Source Code is here for rxdart problem.
class AuthService {
final GoogleSignIn _googleSignIn = GoogleSignIn();
final FirebaseAuth _auth = FirebaseAuth.instance;
final FirebaseFirestore _db = FirebaseFirestore.instance;
Stream<User> user;
Stream<Map<String, dynamic>> profile;
String uuid;
AuthService() {
Stream<User> user = Observable(_auth.authStateChanges);
profile = user.switchMap((User u) {
if (u != null) {
return _db
.collection('users')
.doc(u.uid)
.snapshots()
.map((snap) => snap.data);
} else {
return Observable.just({});
}
});
}
}
It shows error near return Observable.just({}); and next problem arises with this line Stream<User> user = Observable(_auth.authStateChanges);
Help me sort this out and Help me understand my issues.
currentUser is no longer a method, and no longer asynchronous. So the correct invocation now is:
var user = _auth.currentUser;
I recommend keeping the migration guide handy while upgrading your code to this latest version, as there are quite a few of these changes.
In newer versions of the Firebase Auth SDK for Flutter, if you want a stream of auth state events, you should set up an auth state stream using authStateChanges, as shown in the documentation.
FirebaseAuth.instance
.authStateChanges()
.listen((User user) {
if (user == null) {
print('User is currently signed out!');
} else {
print('User is signed in!');
}
});

FirebaseAuth.signInWithEmailAndPassword return null user

I am developing on the flutter platform and using FirebaseAuth library for dart.
When I call FirebaseAuth.signInWithEmailAndPassword(), the user returned in the AuthResult is null.
The problem is that no error was thrown. So I am really confused. According to the docs, there is a list of error code that can be thrown. But in this instance it is just silently failing. Does anyone know why it could be silently failing without communicating any sort of error back?
My code looks as follows...
try {
final AuthResult result = await FirebaseAuth.instance.signInWithEmailAndPassword(
email:email,
password:password
);
final FirebaseUser user = result.user;
if (user != null) {
callback(RequestUserSignInResult.Fail);
return;
}
_user = user;
callback(RequestUserSignInResult.Success);
}
catch (e) {
print("CODE:"+e.code+'\n');
print("MESSAGE:"+e.message+'\n');
callback(RequestUserSignInResult.Success);
}
You seem to have reversed your conditions when checking for the presence of a user in the AuthResult response. But you could also simplify your code like this:
try {
FirebaseAuth.instance.signInWithEmailAndPassword(
email:email,
password:password
).then((authResult){
if(authResult.user != null){
_user = authResult.user;
callback(RequestUserSignInResult.Success);
}else{
callback(RequestUserSignInResult.Fail);
}
});
} catch (e) {
print("CODE:"+e.code+'\n');
print("MESSAGE:"+e.message+'\n');
callback(RequestUserSignInResult.Fail);
}

Firebase/Flutter: reload() not refreshing user.isEmailVerified

I'm sending a verification link when a user registers in the app, but when I try to create a stream that listens for when the user has clicked the verify link in the email.
I'm aware that I somehow need to refresh the user token, but I can't seem to get it to work. I thought reload() method was the one, but maybe I'm just not implementing it correctly.
The problem is that the Stream always returns isEmailVerified == false, only way to make it true is for the user to log out and log in again, which is something I'd like to avoid. How do I do this?
I've created this future:
//CHECKS IF EMAIL IS VERIFIED
Future<bool> checkIfEmailIsVerified() async {
FirebaseUser currUser = await _auth.currentUser();
await currUser.reload();
currUser = await _auth.currentUser();
final bool flag = currUser.isEmailVerified;
if (currUser != null) {
return flag;
} else {
return false;
}
}
and this stream:
//IS EMAILVERIFIED STREAM
Stream<EmailVerified> get emailVerified async* {
final bool isEmailVerified = await checkIfEmailIsVerified();
yield EmailVerified(isEmailVerified);
}
Unfortunately it's necessary to get fresh instance of the user after reload:
User user = FirebaseAuth.instance.currentUser;
if (user != null) {
await user.reload();
user = FirebaseAuth.instance.currentUser;
if (user.emailVerified) {
...
}
}
Try using a single await over chained futures
FirebaseUser currUser = await _auth.currentUser().then((u) => u.reload().then((_) => _auth.currentUser()));
final bool flag = currUser.isEmailVerified;

How to get user id from firebase auth as string?

I'm trying to insert data to firestore with the authenticated user id as the document id but i got null from the parameter.
Please take a look at my script.
void didChangeDependencies() {
uid = '';
super.didChangeDependencies();
}
Future _fetchUID() async {
var auth = AuthProvider.of(context).auth;
return await auth.getCurrentUser().then((user) => _uid = user.uid);
}
_validateAndSubmit() async {
setState(() {
_errorMessage = '';
_isLoading = true;
});
if (_validateAndSave()) {
try {
_fetchUID();
await Report.create(_uid, _suspectName, _plateNumber, _civilizationId,
_drivingLicenseId, _clause, _description);
return Navigator.of(context).pop();
} catch (e) {
setState(() {
_isLoading = false;
_errorMessage = e.message;
});
print(_errorMessage);
throw Exception(e);
}
}
}
In this method below you can see that I have already tried to set the _uid, but I still cannot get the _uid value.
Future _fetchUID() async {
var auth = AuthProvider.of(context).auth;
return await auth.getCurrentUser().then((user) => _uid = user.uid);
}
This is how the getCurrentUser() method looks like.
Future<FirebaseUser> getCurrentUser() async {
FirebaseUser user = await _firebaseAuth.currentUser();
return user;
}
Am I doing it wrong?
First of all, you mixed the Future.then syntax and the async await syntax.
You should probably write your method this way:
void _fetchUID() async {
var auth = AuthProvider.of(context).auth;
_uid = (await auth.getCurrentUser()).uid;
}
If _uid is still null for you after calling _fetchUID this way, then you are simply not signed in, meaning that there is no FirebaseUser as you first need to sign in.
In your _validateAndSubmit method, you also first need to await your _fetchUID call, otherwise it will pass _uid before it has been assigned a value.
...
try {
await _fetchUID();
await Report.create(_uid, ..);
...

Resources