FirestoreService collectionStream not returning value - firebase

I have a button with an onPressed function that returns _shopActivatePage function. It is meant to navigate to either ShopActivatePage() or EmptyContent(), depending on a Future<bool>. However, this function returns the else statement even if there's data in my stream. Without the if else, this function works fine.
The code for the stream is:
#override
//print all docs from firebase collection
Stream<List<Shop>> shopStream() => _service.collectionStream(
path: APIPath.shops(uid),
builder: (data, documentId) => Shop.fromMap(data, documentId),
);
and the function is:
void _shopActivatePage (BuildContext context) async{
final db = Provider.of<Database>(context, listen: false);
if (await db.shopStream().isEmpty) {
Navigator.of(context).push(MaterialPageRoute<void>(
builder: (context) => ShopActivatePage(),
fullscreenDialog: true,
));
} else{
Navigator.of(context).push(MaterialPageRoute<void>(
builder: (context) => EmptyContent(
title: 'Shop activated',
message: 'Your shop has been set up',
),
fullscreenDialog: true,
));
}
}
Thank you so much in advance and sorry if this is an amateur question. Any suggestions is appreciated.

I give you my FirestoreService. I thought you were using one like this.
So in your repository declare
final _service = FirestoreService.instance;
My FirestoreService :
class FirestoreService {
FirestoreService._();
static final instance = FirestoreService._();
void setData({
required String path,
required Map<String, dynamic> data,
}) {
final reference = FirebaseFirestore.instance.doc(path);
reference.set(data, SetOptions(merge: true));
}
Future<void> setDataWithAwait({
required String path,
required Map<String, dynamic> data,
}) async {
final reference = FirebaseFirestore.instance.doc(path);
return reference.set(data, SetOptions(merge: true));
}
void updateData({
required String path,
required Map<String, dynamic> data,
}) {
final reference = FirebaseFirestore.instance.doc(path);
reference.update(data).catchError((onError) {});
}
Future<void> updateDataWithAwait({
required String path,
required Map<String, dynamic> data,
}) async {
final reference = FirebaseFirestore.instance.doc(path);
return reference.update(data).catchError((onError) {});
}
void deleteDoc({required String path}) {
final reference = FirebaseFirestore.instance.doc(path);
reference.delete().catchError((onError) {});
}
Future<void> deleteCollection({required String path}) async {
final reference = FirebaseFirestore.instance.collection(path);
final query = await reference.get();
for (final doc in query.docs) {
doc.reference.delete();
await Future.delayed(const Duration(milliseconds: 200));
}
}
Stream<List<T>> collectionStream<T>({
required String path,
required T Function(Map<String, dynamic>? data) builder,
Query<Map<String, dynamic>?> Function(Query<Map<String, dynamic>?> query)?
queryBuilder,
int Function(T lhs, T rhs)? sort,
}) {
Query<Map<String, dynamic>?> query =
FirebaseFirestore.instance.collection(path);
if (queryBuilder != null) {
query = queryBuilder(query);
}
final Stream<QuerySnapshot<Map<String, dynamic>?>> snapshots =
query.snapshots();
return snapshots.map((snapshot) {
final result = snapshot.docs
.map((snapshot) => builder(snapshot.data()))
.where((value) => value != null)
.toList();
if (sort != null) {
result.sort(sort);
}
return result;
});
}
Stream<List<T>> collectionGroupStream<T>({
required String path,
T Function(Map<String, dynamic>? data)? builder,
Query<Map<String, dynamic>?> Function(Query<Map<String, dynamic>?> query)?
queryBuilder,
int Function(T lhs, T rhs)? sort,
}) {
Query<Map<String, dynamic>?> query =
FirebaseFirestore.instance.collectionGroup(path);
if (queryBuilder != null) {
query = queryBuilder(query);
}
final Stream<QuerySnapshot<Map<String, dynamic>?>> snapshots =
query.snapshots();
return snapshots.map((snapshot) {
final result = snapshot.docs
.map((snapshot) => builder!(snapshot.data()))
.where((value) => value != null)
.toList();
if (sort != null) {
result.sort(sort);
}
return result;
});
}
Future<List<T>> collectionFuture<T>({
required String path,
required T Function(Map<String, dynamic>? data) builder,
Query<Map<String, dynamic>?> Function(Query<Map<String, dynamic>?> query)?
queryBuilder,
int Function(T lhs, T rhs)? sort,
}) async {
Query<Map<String, dynamic>?> query =
FirebaseFirestore.instance.collection(path);
if (queryBuilder != null) {
query = queryBuilder(query);
}
final QuerySnapshot<Map<String, dynamic>?> docs = await query
.get()
.timeout(const Duration(seconds: timeOutSecond), onTimeout: () {
throw Exception();
});
final result = docs.docs
.map((e) => builder(e.data()))
.where((element) => element != null)
.toList();
if (sort != null) {
result.sort(sort);
}
return result;
}
}

Related

Firebase Realtime Databae adds another layer of data

For some reason, my Firebase Realtime Database adds another layer when encoding my data. I am new to using Firebase services, so maybe I entered an incorrect link or smh. -N-1sGl-7VrhyIG7PdDa should not appear. I have a slight idea of why it's happening, but I don't know how to access that last part. Thanks in advance!
Future<void> AddUserGoals(
String userId, String kcal, String p, String c, String f, BuildContext context) async {
final url = Uri.parse(
'https://recipier-e1139-default-rtdb.europe-west1.firebasedatabase.app/usersData/$userId/userGoals.json');
try {
print(kcal);
final response = await http.post(
url,
body: json.encode(
{
'currentBalance': kcal,
'protein': p,
'carbs': c,
'fats': f,
},
),
);
var decodedData = json.decode(response.body) as Map<String, dynamic>;
print(decodedData['currentBalance']);
if (decodedData['error'] == null) {
balance = decodedData['currentBalance'];
} else {
showDialog(
context: context,
builder: (ctx) => const AlertDialog(
title: Text('An error accured'),
content: Text('Please try again later.'),
),
);
}
notifyListeners();
} catch (err) {
rethrow;
}
}
void didChangeDependencies() {
if (_runsForFirstTime == true) {
setState(() {
_isLoading = true;
});
User? user = FirebaseAuth.instance.currentUser;
Provider.of<RecipeProvider>(context).fetchProducts();
Map<String, dynamic> initialData =
ModalRoute.of(context)!.settings.arguments as Map<String, dynamic>;
Provider.of<DiaryProvider>(context, listen: false)
.AddUserGoals(user!.uid, initialData['kcal']!, initialData['p']!,
initialData['c']!, initialData['f']!, context)
.then((_) {
setState(() {
_isLoading = false;
});
});
}
_runsForFirstTime = false;
super.didChangeDependencies();
}
When you call http.post() you tell the REST server to create a new resource (with a unique ID) under the path, so that's what Firebase does.
If you want the server to write the data you pass at the path, use http.put().
Also see:
What is the difference between POST and PUT in HTTP?

Flutter How to model any class instead of FutureBuilder?

I have a model and I want to use my services file to fill it from Firebase but I don't know how to do that ?
I am filling it with FutureBuilder that's okey. But it is exhausting me.
Here is my model:
class ReviewModel {
String? uid;
String? userID;
String? comment;
dynamic rate;
ReviewModel({
this.uid,
this.userID,
this.comment,
this.rate,
});
Map<String, dynamic> toMap() {
return {
'uid': uid,
'userID': userID,
'comment': comment,
'rate': rate,
};
}
factory ReviewModel.fromMap(Map<String, dynamic> map) {
return ReviewModel(
uid: map['uid'],
userID: map['userID'],
comment: map['comment'],
rate: map['rate'],
);
}
factory ReviewModel.fromDatabase(
DocumentSnapshot snapshot, Map<String, dynamic> map) {
return ReviewModel(
uid: snapshot['uid'],
userID: map['userID'],
comment: map['comment'],
rate: map['rate'],
);
}
}
Code is Following below,
Future<ReviewModel> getSalonReviews(String salonUID) async {
CollectionReference aRef = FirebaseFirestore.instance
.collection("salons")
.doc(salonUID)
.collection('bucket')
.doc('reviewbox')
.collection('reviews');
dynamic _doc;
var snapshot;
try {
await aRef.get().then((querySnapshot) => {
for (var dummyDoc in querySnapshot.docs)
{
_doc = dummyDoc.data(),
print(_doc),
}
});
return ReviewModel.fromMap(_doc);
} on FirebaseException catch (e) {
Get.snackbar("Hata", e.code);
rethrow;
}
}
This code is not returning my ReviewModel.
Also I am using GetX and this is my GetX code:
final Rx<ReviewModel> _reviewModel = ReviewModel().obs;
ReviewModel get reviewModel => _reviewModel.value;
set reviewModel(ReviewModel value) => _reviewModel.value;
Future fillReviewModel(String uid) async {
SalonController.instance.reviewModel =
await FakeService().getSalonReviews(uid);
}
it return me this:
And this is my Firebase docs:
How do I achive my ReviewModel with Obx. If I try it, it returns null.
You don't have to return a model you'll do something like this in your prvoider file:
List _reviews = [];
List get reviews => [..._reviews];
// IN your future void function
Future<void> myFunction () async{
myReviews = ...result of forEach;
// now update _reviews
_reviews = [...myReviews];
//And then notify listeners
notifylisteners;
}
And then in your futurebuilder
FutureBuilder(future: Provider.of<myClass>(context, listen:false).myFunction(),
builder:(context, snapshot){
// check the state like the following
if(snapshot.connectionState == ConnectionState.done){
final myValues = Provider.of<myClass>(context, listen:false).reviews;
...do something
return your_values}
if(snapshot.connectionState == ConnectionState.waiting){return progressIndicator}
})

Unhandled Exception: NoSuchMethodError: The method 'addAdvogado' was called on null. On Flutter

I researched other similar questions with this error but I couldn't fix it. I don't know what I'm doing wrong.
My application is not saving to the database when I try to send the information to the form.
What should I do to correct?
I receive the message:
Unhandled Exception: NoSuchMethodError: The method 'addAdvogado' was
called on null. E/flutter ( 7418): Receiver: null E/flutter ( 7418):
Tried calling: addAdvogado(Instance of 'Advogado')
lawyer.dart
class Advogado {
final String id;
final String nome;
final String email;
final String telefone;
final String endereco;
final String numeroOAB;
const Advogado(
{this.id,
#required this.nome,
#required this.email,
#required this.telefone,
#required this.endereco,
#required this.numeroOAB});
Advogado.fromMap(Map snapshot, String id)
: id = snapshot['id'] ?? '',
nome = snapshot['nome'] ?? '',
email = snapshot['email'] ?? '',
telefone = snapshot['telefone'] ?? '',
endereco = snapshot['endereco'] ?? '',
numeroOAB = snapshot['numeroOAB'] ?? '';
toJson() {
return {
"id": id,
"nome": nome,
"email": email,
"telefone": telefone,
"endereco": endereco,
"numeroOAB": numeroOAB,
};
}
}
form_lawyer.dart - Sample code
final _formAdvogado = GlobalKey<FormState>();
final Map<String, String> _dadosForm = {};
Container(
margin: EdgeInsets.all(10.0),
child: RaisedButton(
onPressed: () async {
if (_formAdvogado.currentState.validate()) {
_formAdvogado.currentState.save();
await advogadoProvider.addAdvogado(
Advogado(
nome: 'nome',
email: 'email',
telefone: 'telefone',
endereco: 'endereco',
numeroOAB: 'numeroOAB',
),
);
Navigator.pop(context);
}
},
child: Text("Enviar"),
color: Colors.cyan,
textColor: Colors.white,
),
api_lawyer_firebase.dart
class ApiFirebase {
// final FirebaseFirestore _bd = FirebaseFirestore.instance;
final Future<FirebaseApp> _initialize = Firebase.initializeApp();
FirebaseFirestore _bd = FirebaseFirestore.instance;
final String path;
CollectionReference ref;
ApiFirebase(this.path) {
ref = _bd.collection(path);
}
Future<QuerySnapshot> getColecaoDados() {
return ref.get();
}
Stream<QuerySnapshot> streamColecaoDados() {
return ref.snapshots();
}
Future<DocumentSnapshot> getDocumentoById(String id) {
return ref.doc(id).get();
}
Future<void> removerDocumento(String id) {
return ref.doc(id).delete();
}
Future<DocumentReference> addDocumento(Map dados) {
return ref.add(dados);
}
Future<void> atualizarDocumento(Map dados, String id) {
return ref.doc(id).update(dados);
}
}
CRUD - database_laywer.dart
class DBAdvogado with ChangeNotifier {
ApiFirebase _apiFirebase = locator<ApiFirebase>();
List<Advogado> advogados;
Future<List<Advogado>> buscarAdvogados() async {
var result = await _apiFirebase.getColecaoDados();
advogados =
result.docs.map((doc) => Advogado.fromMap(doc.data(), doc.id)).toList();
return advogados;
}
Stream<QuerySnapshot> buscarAdvogadoAsStream() {
return _apiFirebase.streamColecaoDados();
}
Future<Advogado> getAdvogadoById(String id) async {
var doc = await _apiFirebase.getDocumentoById(id);
return Advogado.fromMap(doc.data(), doc.id);
}
Future removerAdvogado(Advogado dados, String id) async {
await _apiFirebase.atualizarDocumento(dados.toJson(), id);
return;
}
Future addAdvogado(Advogado dados) async {
await _apiFirebase.addDocumento(dados.toJson());
return;
}
}
In general, when there is an error with "something" was called on null it means that the subject on which you are calling "something" is currently null.
You use addAdvogado method in one place on only one variable - in form_lawyer.dart on advogadoProvider. So the question is: how and where do you set advogadoProvider?

How to store image in fire base and store url in firestore

i want to send coupon card to fire store that contain ( name - address - coupon ) and i want to make user set an specific image for every single card
that's my FireStoreService file
class FireStoreService {
FireStoreService._internal();
static final FireStoreService firestoreService = FireStoreService._internal();
Firestore db = Firestore.instance ;
factory FireStoreService() {
return firestoreService;
}
Stream<List<Coupon>> getCoupon() {
return db.collection('coupon').snapshots().map(
(snapshot) => snapshot.documents.map(
(doc) => Coupon.fromMap(doc.data, doc.documentID),
).toList(),
);
}
Future<void> addCoupon(Coupon coupon) {
return db.collection('coupon').add(coupon.toMap());
}
Future<void> deleteCoupon(String id) {
return db.collection('coupon').document(id).delete();
}
Future<void> updateCoupon(Coupon coupon) {
return db.collection('coupon').document(coupon.id).updateData(coupon.toMap());
}
}
and this is Coupon Model file
class Coupon {
final String id;
final String storeName;
final String storeLink;
final String couponCode;
Coupon(
{this.id, this.storeName, this.storeLink, this.couponCode});
Coupon.fromMap(Map<String, dynamic> data, String id)
: storeName = data["storeName"],
storeLink = data['storeLink'],
couponCode = data["couponCode"],
id = id;
Map<String, dynamic> toMap() {
return {
"storeName": storeName,
'storeLink': storeLink,
'couponCode': couponCode,
};
}
}
and this is Image Picker code and it's work fine and picked up the image
Future getImage() async {
try {
File image = await ImagePicker.pickImage(source: ImageSource.gallery);
setState(() {
image = image;
});
} catch (e) {
print(e);
}
}
any help ?
This is a function that asks for an imageFile. If you run your code (getImage function): pass the image variable to the uploadImage function.
String myUrl = await uploadImage(file);
Then you can use setData or updateData to put the url in the database.
Firestore.instance.collection('books').document()
.setData({ 'title': 'title', 'url': '$myUrl' })
final StorageReference storageRef = FirebaseStorage.instance.ref();
Future<String> uploadImage(imageFile) async {
StorageUploadTask uploadTask =
storageRef.child("myPath&Name.jpg").putFile(imageFile);
StorageTaskSnapshot storageSnap = await uploadTask.onComplete;
String downloadURL = await storageSnap.ref.getDownloadURL();
return downloadURL;
}

Flutter - setData to firebase on successfull payment

1) list_profile:
class DetailPage extends StatefulWidget {
final DocumentSnapshot post;
DetailPage({this.post});
#override
_DetailPageState createState() => _DetailPageState();
}
class _DetailPageState extends State<DetailPage> {
bool pressed = false;
String taskname,tasksector,taskpocket,tasklandmark;
int _myTaskType = 0;
String taskVal;
StateModel appState;
bool _loadingVisible = false;
#override
Widget build(BuildContext context) {
// final CounterBloc _counterBloc = BlocProvider.of<CounterBloc>(context);
DateTime now = DateTime.now();
String formattedDate = DateFormat('EEE d MMM y').format(now);
// firebase location to be set
confirm() { // for driver
appState = StateWidget.of(context).state;
//final userId = appState?.firebaseUserAuth?.uid ?? '';
final w_fl = appState?.user?.w_fl ?? '';
final firstName = appState?.user?.firstName ?? '';
final number = appState?.user?.number ?? '';
DocumentReference ds = Firestore.instance
.collection("customer2")
.document("${widget.post.data["driverNumber"]}")
.collection("1")
.document(formattedDate);
Map<String, dynamic> data = {
//"Status": firstName + " $lastName",
"customerName":firstName,
"customerNumber":number,
"time":taskVal,
"status": "Waiting...",
"address":taskname,
"sector":tasksector,
"pocket":taskpocket,
"landmark":tasklandmark,
"payment":"X"
};
ds.setData(data).whenComplete(() {
print('Task created');
});
}
confirm2() { // to fetched only on customer side i.e yourBookings
appState = StateWidget.of(context).state;
//final userId = appState?.firebaseUserAuth?.uid ?? '';
final w_fl = appState?.user?.w_fl ?? '';
final firstName = appState?.user?.firstName ?? '';
final lastName = appState?.user?.lastName ?? '';
final number = appState?.user?.number ?? '';
DocumentReference ds = Firestore.instance
.collection("confirmed_c_rides2")
.document(number)
.collection('1')
.document(formattedDate);
Map<String, dynamic> data = {
//"Status": firstName + " $lastName",
"carImage": "${widget.post.data["carImage"]}",
"driverImage": "${widget.post.data["driverImage"]}",
"experience": "${widget.post.data["experience"]}",
"firstName": "${widget.post.data["driverName"]}",
"gender": "${widget.post.data["gender"]}",
"time": taskVal,
"driverNumber": "${widget.post.data["driverNumber"]}",
//"status": "Waiting..."
"payment":"Complete your payment to confirm"
};
ds.setData(data).whenComplete(() {
print('Task created');
});
}
return Scaffold()
2) check.dart
class CheckRazor extends StatefulWidget {
#override
_CheckRazorState createState() => _CheckRazorState();
}
class _CheckRazorState extends State<CheckRazor> {
Razorpay _razorpay = Razorpay();
var options;
Future payData() async {
try {
_razorpay.open(options);
} catch (e) {
print("errror occured here is ......................./:$e");
}
_razorpay.on(Razorpay.EVENT_PAYMENT_SUCCESS, _handlePaymentSuccess);
_razorpay.on(Razorpay.EVENT_PAYMENT_ERROR, _handlePaymentError);
}
void _handlePaymentSuccess(PaymentSuccessResponse response) async {
print("payment has succedded");
Navigator.pushAndRemoveUntil(
context,
MaterialPageRoute(
builder: (BuildContext context) => SuccessPage(
response: response,
),
),
(Route<dynamic> route) => false,
);
_razorpay.clear();
// Do something when payment succeeds
}
void _handlePaymentError(PaymentFailureResponse response) {..............}
#override
void initState() {
// TODO: implement initState
super.initState();
options = {.......}
#override
Widget build(BuildContext context) {
return Scaffold(
RaisedButton(onPressed(){
confirm();
confirm2();}
);
}
What i want is to create data to firebase only on successful payment only.
In above codes...i have just connected two different codes that is data creation(to firebase) and payment .
1) confirm() & confirm2() are responsible for creating data to firebase.
2) _handlePaymentSuccess() is responsible for successful payment.
Please help!!!
Use shared_preferences,
Add in list.dart:
void saveName() {
savedNamePreferences(taskVal).then((_) {});}
Future<bool> savedNamePreferences(String name) async {
SharedPreferences prefs = await SharedPreferences.getInstance();
prefs.setString("name", name);
return prefs.commit();
}
Future<String> getNamePreferences() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
String name = prefs.getString("name");
return name;
}
And call getNamePreferences() in another class i.e check.dart

Resources