I am working on this Flutter app and I have implemented Firebase Cloud Messaging. I added the following code to make sure I can use the Shared Preferences package. It seems to work, but the functionality does not work correctly.
Extra configuration code
if (Platform.isAndroid) SharedPreferencesAndroid.registerWith();
if (Platform.isIOS) SharedPreferencesIOS.registerWith();
The backgroundhandler in action
Future<void> backgroundHandler(RemoteMessage message) async {
await Firebase.initializeApp();
if (Platform.isAndroid) SharedPreferencesAndroid.registerWith();
if (Platform.isIOS) SharedPreferencesIOS.registerWith();
print("App is in background: Message received ");
final prefs = await SharedPreferences.getInstance();
final listOfTopics = prefs.getStringList('out_of_stock_topics') ?? [];
String topic = 'default_topic';
if (listOfTopics.contains(topic)) {
listOfTopics.remove(topic);
await prefs.setStringList('out_of_stock_topics', listOfTopics);
}
}
The code above deletes the topic in the list. Then the list is set with prefs.setStringList. I checked, and the code goes into the if statement. It removes the item from the list. But something goes wrong in prefs.setStringList I suppose.
Because later I use the following code to check the items in the 'out_of_stock_topics' list.
Code to check list of topics
final prefs = await SharedPreferences.getInstance();
final listOfTopics =
prefs.getStringList('out_of_stock_topics') ?? [];
print(listOfTopics);
But the topic is not correctly deleted and is still there. I think there is something wrong in the backend of the backgroundhandler. I tested this feature with 2 buttons: "add topic" and "delete topic". And with those separate buttons it does delete the item from the 'out_of_stock_topics' list.
Does anyone know how to fix this problem?
Thanks!
Related
I am trying to get user email,save to shared preferences and use as collection name in another file.
my code to save
Future<void> saveEmail() async {
var sharedPreferences = await SharedPreferences.getInstance();
sharedPreferences.setString("email", _emailKontroller.text);}
no problem here, I can save data to sharedPreferences and read data from another file.
my code to read
#override
void initState() {
// TODO: implement initState
void initilaizeEmail() async {
var sharedPreferences = await SharedPreferences.getInstance();
_email = sharedPreferences.getString("email");
print(_email);
}
initilaizeEmail();
setState(() {});
}
output
I/flutter ( 3274): a#a.com
where I use as parameter my sharedPreferences Data:
query: FirebaseFirestore.instance
.collection("test")
.doc("$_email")
.collection("class 0"),
// to fetch real-time data
isLive: false,
I can not see anything on screen but, if I delete
_email
and type "a#a.com" manually everything works.What is the problem?
The problem is that initilaizeEmail is an async method, and you're not waiting for its result. To fix this:
await initilaizeEmail();
I also recommend fixing the name of the method to be initializeEmail. While it won't change the behavior, spelling mistakes tend distract from other problems.
I solved my problem with using
Future Builder
My application was writing to Firestore but suddenly stopped working. When I try to write to Firestore my write method does not complete. I have made the following simple test method to troubleshoot my problem but can't seem to figure out what is going on:
//In database.dart
Future<void> testSet() async {
final reference = FirebaseFirestore.instance.doc('users/test');
await reference.set({'TEST': 'Value'});
print('This is never printing');
}
//In home_page.dart called via clicking a button
Future<void> _testSet(context) async {
final database = Provider.of<Database>(context, listen: false);
await database.testSet();
}
I have tried emptying my Firestore Database as well as adding a users collection; however nothing has worked. Why am I unable to write to Firestore?
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 have a Firebase Firestore database as you can see in the picture. I'd like to get every document from the questions collection with their fields.
I found the following solution on the internet:
//in this list we store the data
List adatok = [];
Future<void> getData(){
databaseReference.getDocuments().then((QuerySnapshot snapshot) {
snapshot.documents.forEach((f){
data = f.data;
adatok.add(data);
print(adatok.length);
print(adatok);
}
);
}
);
}
My problem is that when I call this function (in an onPresed() function of a button), for the first time of pressing the adatok list is empty. But when I press the button for the second time, it contains every data which I wanted to acquire.
Did I do something wrong? Is there another way to get the data?
The layout of the database
Use the code below:
List adatok = [];
Future<void> getData() async{
QuerySnapshot snapshot = await databaseReference.getDocuments();
snapshot.documents.forEach((f){
data = f.data;
adatok.add(data);
print(adatok.length);
print(adatok);
}
}
By this way, The program waits until it gets all the documents.
and then adds it to your snapshots.
Also you have to change your onPressed() function to async/await like the following:
onPressed:() async{
await getData();
/...
}
So the program waits until getData() finishes.
I'm a total newbie to Flutter and I'm trying to add some data from Cloud Firestore to a list in Flutter, but having issues. I try to add the element, but after executing, the element isn't there. It's not throwing an exception or anything either. Maybe someone else has some advice for me!
I have tried changing the type of list (capture the doc from Cloud Firestore instead of data within the doc, same issue), I have also debugPrinted the data I am trying to store to make sure it exists, it does. I have done basic troubleshooting like running flutter clean as well. I am on the latest version of Flutter.
Firestore db = firestore();
List<String> getString() {
var dataList = new List<String>();
db.collection('Users').get().then((querySnapshot) {
querySnapshot.forEach((doc) {
dataList.add(doc.get('First name'));
});
});
debugPrint(dataList.first);
return dataList;
The list is empty, though it should contain the "First name" field on this Cloud Firestore doc. Again, verified the data does exist and prints when calling debugPrint.
The db.collection('Users').get() is a async function, so debugPrint(dataList.first); executes before of the end of your firestores get, because that your array returns empty.
If you try it:
db.collection('Users').get().then((querySnapshot) {
querySnapshot.forEach((doc) {
dataList.add(doc.get('First name'));
});
debugPrint(dataList.first);
});
You will see your data.
You can use await to wait the call finishes, so you must return a Future and use async key word on function declaration. This is a conceipt that you must know of flutter async functions (Async Flutter). So, the code below can solve your problem.
Firestore db = firestore();
Future <List<String>> getString() async {
var dataList = new List<String>();
var result = await db.collection('Users').get();
result.forEach((doc) {
dataList.add(doc.get('First name'));
});
debugPrint(dataList.first);
return dataList;
}