I have one String type variable API_URL in flutter and I want to get its value from Firebase Remote Config. I wrote following code to fetch it...
Future<String> get_api_url() async {
final RemoteConfig remoteConfig = await RemoteConfig.instance;
await remoteConfig.fetch(expiration: const Duration(hours: 0));
await remoteConfig.activateFetched();
return remoteConfig.getString('api_url');
}
It is returning value but I am not able to store it in variable named API_URL. May be I can use FutureBuilder but not sure what to do. So your help will be much appreciated.
Related
I am using Flutter and I would like to retrieve some data from my realtime database Firebase. I have the following data stored in the my realtime database Firebase:
How can I get each piece of information from it? For example I would like to get the name 'Tom' only?
Reading through firebase documentation you can see that how we read and write data from RTDMS firebase.
static Future<List<PostModel>> getPost() async {
Query postsSnapshot = await FirebaseDatabase.instance
.reference()
.child("posts")
.orderByKey();
print(postsSnapshot); // to debug and see if data is returned
List<PostModel> posts;
Map<dynamic, dynamic> values = postsSnapshot.data.value;
values.forEach((key, values) {
posts.add(values);
});
return posts;
}
your can call this function at the time of build the widget or after any action
FirebaseDatabase.instance.ref("users").onValue.listen((event) {
final data =
Map<String, dynamic>.from(event.snapshot.value as Map,);
data.forEach((key, value) {
log("$value");
});
});
This code is from: https://blog.logrocket.com/flutter-push-notifications-with-firebase-cloud-messaging/
void registerNotification() async {
// 1. Initialize the Firebase app
await Firebase.initializeApp();
// 2. Instantiate Firebase Messaging
_messaging = FirebaseMessaging.instance;
.......
}
Here for Firebase.initializeApp() they have used await and async.
How do I know await is required for this function to work properlty?
Doc are here: https://firebase.google.com/docs/reference/node/firebase#initializeapp
I didn't see anything special mentioned regarding await in docs.
Here is the implementation for initializeApp() which you can find in the documentation from firebase_core:
static Future<FirebaseApp> initializeApp({
String? name,
FirebaseOptions? options,
}) async {
FirebaseAppPlatform app = await _delegate.initializeApp(
name: name,
options: options,
);
return FirebaseApp._(app);
}
As you can see the return type is a Future<FirebaseApp> which means that it is an asynchronous method and that you should use the keyword await to ensure your operation will be completed before continuing to execute your code.
As you might already know await can only be used inside an async method.
The documentation you've pointed out is for Node.js, here's a link to the FlutterFire's "Getting Started" docs. There it says:
To initialize FlutterFire, call the initializeApp method on the Firebase class:
await Firebase.initializeApp();
The method is asynchronous and returns a Future, so you need to ensure it has completed before displaying your main application.
It is common that "initialize" functions are Futures, and thus should be awaited for. You can check that by looking at the return type of the function, which is documented here.
You can click inside the function to see what's behind the scene
For example, I've clicked it and here's the result
so It returns Future of FirebaseApp which is required async and await to get the value inside of the Future
Hi I have reviewed previous answers to similar questions (eg here) but they do not fix my issue.
I have an app in which the user records and audio snippet which is then uploaded to firebase storage. Everything works in general, but currently there is no folder structure (so all users files would save to the same top level). Therefore I am trying to call a user uid to create a unique user foler. Since the user also logs in to firestore DB first I have a specified user.uid
I have a method to call the current user
Future getCurrentUser() async {
final FirebaseUser user = await _auth.currentUser(); # _auth is instance of FirebaseAuth
return user;
If I attach this to an onPressed event of a button I get the following
flutter: user Information is
flutter: D3sR4sKXXXXYToYQrmkkxmBNGvWq1
However if I call the same function within my 'stop' recording function I get a different result.
Stop recording () async {
// some audio commands....
var folder = _auth.getCurrentUser().toString();
print('Folder name is: ' + folder);
This gives me
flutter: folder name is: Instance of 'Future<dynamic>'
I don't know if this is connected but I noticed some differences in the firestore response compared to some older online tutorials. For example, if I change my current user method as suggested in other StackOverflow examples (eg here ) to
Future getCurrentUser() async {
final FirebaseUser user = await _auth.currentUser();
return user.uid;
I get the following exception whether called in code or via onPressed(though the command completes),
flutter: user Information is
[VERBOSE-2:ui_dart_state.cc(157)] Unhandled Exception: NoSuchMethodError: Class 'String' has no instance getter 'uid'.
Receiver: "D3sR4sKXXXXYToYQrmkkxmBNGvWq1"
I do not get this message when calling user.uid directly from the response from the users initial firestore login.
This:
Stop recording () async {
// some audio commands....
var folder = _auth.getCurrentUser().toString();
print('Folder name is: ' + folder);
gives you a Future because the method that you created returns a Future which means it is asynchronous, that's why you use async/await to get the data from the future operation:
Future<FirebaseUser> getCurrentUser() async {
return await _auth.currentUser();
}
And now when you call this method you can do the following:
FirebaseUser userResult = await getCurrentUser();
print(userResult.uid);
Basically currentUser() returns a Future<FirebaseUser>, and the FirebaseUser class extends the class UserInfo which contains the property uid.
https://github.com/FirebaseExtended/flutterfire/blob/master/packages/firebase_auth/firebase_auth/lib/src/user_info.dart
I have a stream which read user data from firebase. I trigger it after signin, it works perfectly. I show the data in my appbar. When I update firebase manually, I want to see the new date instantly on my appbar. First, I guessed there is something wrong with my appbar but then I noticed that my stream do not triggered when I update firebase data. Here is my stream code snippet. What am I missing?
static Future<User> userDataStream(userID) async {
print("userDataStream");
final databaseReference = Firestore.instance;
User currentUser = User();
await for (var snapshot in databaseReference
.collection('users')
.where('userID', isEqualTo: userID)
.snapshots()) {
currentUser.userName = snapshot.documents.first.data['userName'];
currentUser.email = snapshot.documents.first.data['email'];
currentUser.userID = snapshot.documents.first.data['userID'];
currentUser.level = snapshot.documents.first.data['level'];
currentUser.balance = snapshot.documents.first.data['balance'];
print(currentUser.balance);
return currentUser;
}
return currentUser;
}
How you are using this stream matters. await for starts listening to the user, then you do return currentUser; in it and break the await for. Therefore, it cannot keep listening to the stream in the future.
Instead of the return currentUser; inside await for, you can do something like setState((){this.renderedUser = currentUser;}) so that the user that comes from the server becomes the rendered one. If you do that, also add if (!mounted) return; inside the await for so that you stop listening to it when you realize you are in a different screen.
A better alternative may be to use the StreamBuilder widget.
If you run your current code, and make a change to the database, the print statement should be run again. That's because the snapshots is already listening for changes to the database, and calling your code when those happens.
The problem is that you return a Future<User> and a future can only be resolved (get a value) once. If you want to return live data that'd be a Stream<User> (and typically a StreamBuilder instead of a FutureBuilder to build a UI from it).
I try to read listen to a stream from Firebase with this code:
visibleListsIds.forEach((final String listId) async {
final Stream<List<WishList>> wishListStream = sharedCollection()
.document(listId)
.snapshots()
.map((DocumentSnapshot documentSnapshot) {
log.d("updated Document Snapshot: ${documentSnapshot.data}");
return [
_getSerializers()
.deserializeWith(WishList.serializer, documentSnapshot.data)
];
});
wishListStreams.add(wishListStream);
});
Where sharedCollection() gives me access to the Firestore instance with the correct collection
I try to write to the collection, with this code
DocumentReference postRef = sharedCollection().document(wishList.listId);
firestore.runTransaction((Transaction tx) async {
DocumentSnapshot postSnapshot = await tx.get(postRef);
if (postSnapshot.exists) {
await tx.update(postRef,
_getSerializers().serializeWith(WishList.serializer, wishList));
} else {
await tx.set(postRef,
_getSerializers().serializeWith(WishList.serializer, wishList));
}
});
What happens:
I can write to Firebase but only one change at a time. When I do the next update, the last one gets reverted.
I can see the updated data only in the Firebase Console. The App does not show it and it does not show in the log at log.d("updated Document Snapshot: ${documentSnapshot.data}");.
When I modify data in the Firebase Console, I can also not see it change
BUT once I reload the App, all the Data syncs up to the current state of the Firebase Console
Anyone know why I do not get updates with the Stream?
Thanks for your help.
I use the Cloud Firestore Plugin:
cloud_firestore: ^0.13.0+1