Flutter: PlatformException(error, Invalid document reference. Document references must have an even number of segments, but <x> has 1, null) - firebase

I have the following in my app:
stream: Firestore.instance.collection('stores').document(currentUserUID).snapshots(),
builder: (BuildContext context, AsyncSnapshot<DocumentSnapshot> snapshot) {
if (snapshot.hasData) {
return ListView.builder(
//do some stuff here with the data
} else {
return LoadingAnimation();
}
}
}
}
Pretty standard, but I am getting the error listed above.
I have vertified that currentUserID populates with the correct data before this stream is called.
In testing I have found that this error is perhaps likely caused by the fact that at runtime, "if (snapshot.hasData) {" shows me that there is no data in the snapshot yet. If I do anything at all, like minimise the app and refocus it again, all the data loads. So it simply just needs a redraw.
Is there a way to do an "await" or something on this? There must be a simple fix for this problem, seems to be a simple issue, but I just can't find a solution in any of the other threads about this.
Anyone have any ideas on how I can either do an await on this stream, or force it to update when it receives data (I kinda thought that was the whole point of a stream, but this examples proves that it doesn't do this).

If the error message actually refers to this code, that means currentUserUID is probably an empty string. This is a very common mistake - if you do a Google search for the error message, you will see many others making the same mistake.
Print the value of currentUserUID just before you use it in order to verify that it contains the value that you expect.

Related

Does this stream work the way I imagine it would?

I have a bug in my app that could be caused by several things. To share the whole problem would be too much, so I am dividing the questions into individual areas that might cause the problem.
One area that could cause the problem is this:
I have created a stream that should returns the blue underlined number.
Therefore, I use this stream:
Stream<QuerySnapshot> getStufe() {
var stufe = userTodos.where('Stufe', isEqualTo: 1);
stufe = stufe.where('userID', isEqualTo: userID);
return stufe.snapshots();
}
Does this stream work the way I imagine it would?

Flutter gives null error, but works after restart

I am new to Flutter, I am trying to fetch data from firestore collection. I am using FutureBuilder with Provider, but it shows null error on initial & runs perfectly after restarting the app.
Here is the code to fetch the data:
FutureBuilder<QuerySnapshot>(
future: FirebaseFirestore.instance
.collection(collec.collectionProducts)
.get(),
builder: (context, snapshot) {
return Consumer<CartItemCounter>(
builder: (BuildContext context, CartItemCounter cart, _) {
if (cart.checkProductAddedToCart(model.productId)) {
return Row(....);
Error
code for futurebuilder
code for ui
(here i have changed the collection name)
How can i solve it. I have tried every solution available on online. Thank you
Where is the error coming from?
According to this, the issue is coming from your Consumer<CartItemCounter>.
What does the error mean?
This error, The method 'x' was called on null., means that the class where this x function is written, that class is null.
What is the reason for this error in my code?
Your Consumer<CartItemCounter> provides an instance of CartItemCounter by the name cart. Then, you call function checkProductAddedToCart.
The error message is telling you that cart is null which is being given to you by the Consumer widget. This means that Consumer probably also did not find that Provider. I expect that there should be an error log by Provider, telling you that CartItemCounter was not found.
Possible Solution
Try 'providing' CartItemCounter.
How do you do that? Go to the top of your app's widget tree to MaterialApp, wrap it inside a MultiProvider or ChangeNotifierProvider and then pass your new CartItemCounter as value.
Read Official Provider Docs for more info on how to expose a provider.
You need to upload your complete log, so that I can further help you.
Always check the result for the future builder, ie snapshot has data.
Place a switch condition or if-else bock depending on the status of the snapshot.
check the example from the official doc here

Flutter and Firebase: Return all images from Firebase Storage

I have seen a few articles written online by people pertaining to be able to do this, but they only tell you how to do this with a specific, controlled list of images where they also know all the filenames beforehand.
There is also this "answer" posted here: Flutter - Get all images from firebase storage which does not actually resolve this issue at all as it suggests a .listAll() method for the recommended plugin, but there is no such method as .listAll() using the suggested plugin.
I need to be able to not know how many images are in Firebase storage, or what they might be called, just to return everything stored there.
UPDATE:
So because Firebase is full of so many limitations that it hardly qualifies as a database at all, it seems we may have to keep the images in Firebase Storage and a reference list of these in a Firebase Realtime Database Document.
I am stuck on the actual implementation of this however, as I am not even sure firstly how best to go about this. What I am attempting to do is store all the Storage image URLs in an array (if this is not the best way to do this, let me know!):
Firebase Structure
collection -> document -> fields
userData profileImages URLs (array)
My first issue is that I don't know how to append new data to the existing array, it seems to just overwrite it each time I add a new item so that I only ever have one string in the array in the database:
Firestore.instance.collection('userData').document('profileImages').updateData({
'URLs': _uploadedFileURL,
});
Then after this I am also not sure how to actually retrieve the full array of data later when I need it:
Container(
child: StreamBuilder(
stream: Firestore.instance.collection('userData').document('profileImages').snapshots(),
builder: (BuildContext context, AsyncSnapshot<DocumentSnapshot> snapshot) {
if (!snapshot.hasData) {
return LoadingAnimationBasic();
}
if (snapshot.data.data == null) {
return LoadingAnimationBasic();
} else {
return ListView(
shrinkWrap: true,
children: _buildProfileGallery(snapshot),
);
}
},
),
),
And then the function:
_buildProfileGallery(AsyncSnapshot<DocumentSnapshot> snapshot) {
int test = snapshot.data["URLs"].length;
print('URLs in List: ' + test.toString());
return snapshot.data.data.map(???);
}
I have no idea what to put as the parameters of this map, as the hint text is insane:
MapEntry(K2, V2> f(String key, V value)
I can't even begin to guess what this means.
Am I on the right track? Am I on the right planet?
The ability to list files was added to Firebase's client-side SDKs for Android, iOS and JavaScript last year, but has not yet landed in the FlutterFire bindings.
The answer to the question you linked, refers to a pull request on the FlutterFire open-source project that adds this functionality. So while somebody wrote code to allow listing of files in Flutter too, this code hasn't been added to a release so far. So the only way to use that code now, is to build your own version of the FlutterFire library for firebase_storage.
Without the ability to list files in the Firebase Storage API, you'll have to revert back to what everyone did before this feature was added: keeping a list of the files in a secondary location, such as the Firebase Realtime Database or Cloud Firestore.

Retrieving snapshots from firestore sub-collection to dart/flutter object

New here. I've googled everything and can't figure this out.
The first two functions below work flawlessly the third always return null immediately without calling my ListFromSnapShot function, which just turns the map into a list. I am assuming
I'm not calling the Firestore correctly but I have no idea how to do this properly.
final CollectionReference customerCollection = Firestore.instance.collection('customers');
final CollectionReference jobCollection = Firestore.instance.collection('jobs');
// get user doc stream
Stream<UserData> get userData {
return customerCollection.document(uid).snapshots()
.map(_userDataFromSnapshot);
}
//Returns only snapshots with matching customer name to StreamProvider object
Stream<List<Job>> get jobQuery {
return jobCollection.where('customerName', isEqualTo: currentCustomer.companyName)
.snapshots()
.map(_jobListFromSnapshot);
}
//The following always returns Null
Stream<List<JobSectionModel>> get jobQuerySections {
return jobCollection.document('Family Dollar').collection('sections')
.snapshots()
.map(_jobSectionListFromSnapshot);
This is my database structure
Base Collection
Subcollection
Any help would be greatly appreciated.
The code above does work, the problem, after several frustrating days, ended up being random spaces in the firestore path. I'm posting this as an answer because after googling this there were many others with a similar problem and I don't want them to go through the same frustration. Firestore will not show this until you literally click on the path name and it will not crash your program, it just returns nothing.
Do yourself a favor and use the .trim() function when adding data and if you do it manually on firestore make sure there's no trailing spaces.
Also I rebuilt the code as follows which also works (without spaces of course)
Stream<QuerySnapshot> getjobQuerySections(BuildContext context) async*{
yield* jobCollection.document('T-MOBILE').collection('whyspaces').snapshots();
Hope this helps someone. Good Luck

Getting data without a key. Only with information on child nodes

I'm having a really hard time understanding how Nosql works so I hope someone can help me understand it a bit better.
I'm trying to make a simple chat application (One to one chat support and chat groups) and want to dislay a list of all the conversations that the current user is in. This is my table for it.
I tried getting the data in several ways. But what I currently have is this (Which should work according to the internet, but doesn't).
_membersRef.equalTo(1508, key: '1508').once().then((DataSnapshot snap) {
print(snap.value);
});
I also tried
_membersRef.startAt(1508).endAt(1508).once().then((DataSnapshot snap) {
print(snap.value);
});
What I want my code to do is return all records that have my account_id in them (1508 in this case). So it should return the record "one".
So if I change the uid in the code to 1509 it should return "One" and "two". How can I make this happen?
To get the key one try this:
_membersRef.orderByChild('1508').equalTo(true).once().then((DataSnapshot snap) {
print(snap.value);
});
the snapshot is at child members then you order it according to child 1508 which is equalTo(true).

Resources