transaction problem with function in flutter - dart

I try to make transaction to insert data in database using sqflite
i can't put this transaction into function for null safety problem for i can't know the
return type of this function
Future insertDataBase() async{
return await dataBase?.transaction(
(txn) {
txn.rawInsert('').then((value)
{
print('data added');
}
).catchError
(
(error){
print('error row : ${error.toString()}');
});
}
);
}```

Related

Mapping a Stream<List> to another type is returning a Stream<Null>

I'm trying to transform a Stream of a list of one type into a Stream of a list of another type, and having an issue with this.
I have this list of Habits that I'm streaming from Firebase, and I want to accept that stream in a function, and return a new stream that is a list of ViewModels of another type from it. But my function is returning a stream of the wrong type.
Here is my code:
Stream<List<HabitCompletionViewModel>> _getTodaysHabits(
Stream<List<Habit>> habitsStream) {
var result = habitsStream.map((habitsList) {
habitsList.map(
(habit) async {
await _getHabitCompletionsCurrent(habit);
HabitCompletion completion = habit.completions!.firstWhere(
(completion) => completion.date
.dayEqualityCheck(DateTime.now().startOfDate()));
return HabitCompletionViewModel(completion: completion, habit: habit);
},
).toList();
});
return result;
}
I am getting a compile error because the result variable is showing as type Stream<Null> when I hover over it, where I would expect it to be Stream<List<HabitCompletionViewModel>>. Any idea what I'm doing wrong?
Your outer .map call does not have a return statement which is why you are getting a Stream<Null>.
So add a return statement like so:
Stream<List<HabitCompletionViewModel>> _getTodaysHabits(
Stream<List<Habit>> habitsStream) {
var result = habitsStream.map((habitsList) {
// added return statement here
return habitsList.map(
(habit) async {
await _getHabitCompletionsCurrent(habit);
HabitCompletion completion = habit.completions!.firstWhere(
(completion) =>
completion.date.dayEqualityCheck(DateTime.now().startOfDate()));
return HabitCompletionViewModel(completion: completion, habit: habit);
},
).toList();
});
return result;
}
However the above code still has an error because it is now returning a Stream<List<Future<HabitCompletionViewModel>>> instead of the desired Stream<List<HabitCompletionViewModel>>. To solve this you can use .asyncMap instead of .map.
Stream<List<HabitCompletionViewModel>> _getTodaysHabits(
Stream<List<Habit>> habitsStream) {
var result = habitsStream.asyncMap((habitsList) {
return Stream.fromIterable(habitsList).asyncMap(
(habit) async {
await _getHabitCompletionsCurrent(habit);
HabitCompletion completion = habit.completions!.firstWhere(
(completion) =>
completion.date.dayEqualityCheck(DateTime.now().startOfDate()));
return HabitCompletionViewModel(completion: completion, habit: habit);
},
).toList();
});
return result;
}

Why future is not getting complete?

I need to get all the document inside this collection which much these query - I'm receiving all the documents successfully but the future never ends.
I tried WhenComplete but still not working.
Future<Null> getOldVac(anId) async {
print("getOldVac");
await Firestore.instance
.collection("users")
.document(userId)
.collection("animals")
.document(anId)
.collection("anMedication")
.where("type", isEqualTo: "vac")
.where("result", isEqualTo: "")
.snapshots()
.forEach((onValue) {
print(onValue);
}).then((onValue) {
print("Done");
}).catchError((onError) {
print(onError);
});
}
I need to print "Done" once all the future is complete.
You need to return something, can be the null that you are using or a void or throw some error.
try to put return in the front of your await like this:
return await Firestore.instance
.collection("users")
.document(userId)
.collection("animals")
.document(anId)
.collection("anMedication")
.where("type", isEqualTo: "vac")
.where("result", isEqualTo: "")
.snapshots()
.forEach((onValue) {
print(onValue);
return null;
}).then((onValue) {
print("Done");
return null;
}).catchError((onError) {
print(onError);
throw onError;
});
You are mixing promises with async await!

How to return from then of a Future in dart

I have a function which does some asynchronous operations and I want to return the status of the operation back to the caller. How can I achieve this?
Future<bool> setData() async {
Firestore.instance.collection("test").document('$id').setData({
'id': 'test'
}).then((onValue) {
print('Data set success');
return true;
}).catchError((onError) {
print('Data set Error!!!');
return false;
});
}
//Calling
final status = await setData();
if(status){
//do success
}
But this function complains that it doesn't end with a return statement. What is the logical mistake I'm making here?
You miss a return in your setData function
return Firestore.instance....

flutter firebase wire operation

This is my code for add new address in firebase realtime database
Future<bool> addAddress(Address adr)async{
database = FirebaseDatabase(app: app);
await database
.reference()
.child(table_name).child(uid)
.set(adr).then((onValue){
print("adress add complected");
return true;
}).catchError((onError){
print("adress add failed $uid");
print(onError);
return false;
});
}
but it returning error
Invalid argument: Instance of 'Address'
Where is i am doging wrong ?
Your input for set() has to be type Map, so you have to do something like this:
Future<bool> addAddress(Address adr)async{
database = FirebaseDatabase(app: app);
await database
.reference()
.child(table_name).child(uid)
.set({
"country": adr.count,
"state": adr.state,
"city": adr.city,
}).then((onValue){
print("adress add complected");
return true;
}).catchError((onError){
print("adress add failed $uid");
print(onError);
return false;
});
}

Loading a file using rootBundle

I need to load a string from a file. The following code always returns null:
static String l( String name ) {
String contents;
rootBundle
.loadString( 'i10n/de.yaml' )
.then( (String r) { contents = 'found'; print( 'then()' ); })
.catchError( (e) { contents = '#Error#'; print( 'catchError()' ); })
.whenComplete(() { contents = 'dd'; print( 'whenComplete()' ); })
;
print( 'after' );
if ( null == contents ) {
return '#null#';
}
String doc = loadYaml( contents );
return doc;
}
I have added this to the flutter: section in pupspec.yaml section:
assets:
- i10n/de.yaml
- i10n/en.yaml
The file i10n/de.yaml exists.
I'm aware, that rootBundle.loadString() is async. Therefore I appended the then() call - assuming that
(String r) { contents = 'found'; }
only gets executed if the Future returned by rootBundle.loadString() is able to return a value.
Actually, the method always returns '#null#'. Therefore, I added the print() statements, which output this:
I/flutter (22382): after
I/flutter (22382): then()
I/flutter (22382): whenComplete()
OK, obviously the future of loadString() executes later than the final print() statement.
Q: But how do I force the future to execute, so that I may retrieve its value?
In other words: How do I wrap some async stuff in certain code to retrieve its value immediately?
PS: First day of flutter/dart. Probably a trivial question...
the .then() is getting executed, but after the rest of the body. As you mention loadString() returns a Future, so completes in the future. To wait for a Future to complete use await. (Note that when you mark the function as async, the function must now return a Future itself - as it has to wait for loadString to complete in the future, so it itself has to complete in the future...) When you call l('something') you will have to await the result.
Future<String> l(String name) async {
try {
String contents = await rootBundle.loadString('i10n/de.yaml');
return contents == null ? '#null#' : loadYaml(contents);
} catch (e) {
return 'oops $e';
}
}
It's no big deal that lots of your utility functions become async as a result of having to wait for things (there's a lot of waiting - for files to read, http requests to complete, etc). You'll eventually end up at the top with something like (call this from initState)
refresh(String s) {
l(s).then((r) {
setState(() {
i18nStuff = r;
});
});
}
to set the state of your Widget when the i18nStuff is ready, and a Widget that has this in its build to switch between a dummy ui for the few milliseconds until it's ready, and then the real UI.
Widget build() {
if (i18nStuff == null) {
return new Container();
}
return new Column(
// build the real UI here
);
}

Resources