Stream created using StreamController and await for - flutter

I am learning stream in dart.
The following code shows a generator method(countStream) and a method that uses the stream(sumStream), they are from sample code from dart.dev. It works, meaning that
I can see the following output at the end.
end of for
total = 15
However, when I try to create a stream using makeCounter where I use StreamController to create a stream instead of generator (async* and yield), I can see the following output.
add
add
add
add
add
I suppose that makeCounter works because I see five "add".
How to fix this problem? Or It may impossible to create a stream with StreamController with await for.
Future<int> sumStream(Stream<int> stream) async {
var sum = 0;
await for (final value in stream) {
sum += value;
}
print("end of for");
return sum;
}
Stream<int> makeCounter(int to) {
var controller = StreamController<int>();
int counter = 0;
void tick(Timer timer) {
counter++;
print("add");
controller.add(counter);
if (counter >= to) {
timer.cancel();
}
}
Timer.periodic(Duration(seconds: 1), tick);
return controller.stream;
}
Stream<int> countStream(int to) async* {
for (int i = 1; i <= to; i++) {
await Future.delayed(Duration(seconds: 1));
yield i;
}
}
void test() async {
var stream = countStream(5);
//var stream = makeCounter(5); // this does not work correctly
var sum = await sumStream(stream);
print("total = $sum");
}

Related

How to retrieve the value of a listener passed to a Stream?

Stream<int> get ints async* {
yield 100;
}
Future<int> foo(int i) async {
print(i);
return 0;
}
void main() {
final subscription = ints.listen(foo);
// I thought something like this could work...
subscription.asFuture().then((value) => print('value = $value'));
}
How can I retrieve the value of foo function (i.e. 0) from the StreamSubscription instance?

Network foor loop async

I want to a lot of request in for loop.This is my network method.
Future postdata<T, F extends ApiResponseFromJson>({
#required T? requestmodel,
#required F? responsemodel,
#required String? path,
}) async {
try {
final response = await dio.post(path!, data: requestmodel);
print(ApiPath.API_URL + path);
if (response.data is List) {
return List<F>.from(
(response.data).map((e) => responsemodel!.fromJson(e)));
}
return responsemodel!.fromJson(response.data);
} on DioError catch (e) {
final errorMessage = DioExceptions.fromDioError(e).toString();
showSnackBarDialog("Hata", errorMessage, const Icon(Icons.error))
};
List<CarModel> carModel=[CarModel(),CarModel(),CarModel()...]
Future<ResponseModel?> postData(int index) async {
responseModel.carModel = carModel[i];
responseModel= await _networkService
.postdata<RequestModel, ResponseModel>(
requestmodel: requestModel,
responsemodel: ResponseModel(),
path: ApiPath.API_DATA_LINK);
return responseModel;
}
_allListModel() async {
for (var i = 0; i < carModel.length; i++) {
differentList.add(await postData(i));
}
I have different list and i need request list of lenght.But in for loop response always waiting the other index. But i dont need wait. Cause networkModel goes to list of lenght different API and i don't know which one result is coming to first.
I want to request in for loop and i don't need to the other index. How can i do ?
This code call all request at once, just remove await and the method then is called when request end:
_allListModel() {
for (var i = 0; i < carModel.length; i++) {
postData(i).then((value) {
differentList.add(value);
});
}
}
You should use Future.wait to wait for multiple futures. You start all of them and then you wait until all are done and add all the results to the list.
Future<void> _allListModel() async {
var futures = <Future<>>[]
for (var i = 0; i < carModel.length; i++) {
futures.add(postData(i));
}
var responses = await Future.wait(futures);
differentList.addAll(responses);
}

slow down for-loop to count from 15 to 5 in 10 seconds

I try to delay the output for my for-loop and print a count down a value once a second.
This is what I'm trying to do, but somehow it doesn't works.
void main() {
var actualCurrent = 5; //Value from DB later
var delayedCurrent = 15; // Value gets set in programm
for (int i=delayedCurrent; i > actualCurrent; i--) {
Future.delayed(Duration(seconds: 1),(){
print('value: '+delayedCurrent.toString());
delayedCurrent --;
});
}
}
If I put i-- into Future.delayed the programm crashes.
What is to do to count from 15 to 5 in 10 seconds?
We're running main on Future, that's why we need to make this function async to await.
on dartpad
void main() async {
var actualCurrent = 5; //Value from DB later
var delayedCurrent = 15; // Value gets set in programm
for (int i = delayedCurrent; i > actualCurrent; i--) {
await Future.delayed(Duration(seconds: 1), () {
print('value: ' + delayedCurrent.toString());
delayedCurrent--;
});
}
}
just add async and await for the delayed method. this will work.
void main() async{
var actualCurrent = 5; //Value from DB later
var delayedCurrent = 15; // Value gets set in programm
for (int i=delayedCurrent; i > actualCurrent; i--) {
await Future.delayed(Duration(seconds: 1),(){
print('value: '+delayedCurrent.toString());
delayedCurrent --;
});
}
}

Data not being added in a list in Flutter

i have a list of objects :
List<Hairdresser> HairdressersData = new List<Hairdresser>();
and i am using this method to add data in this list :
void asyncInitState() async {
Hairdressercontroller HController = Hairdressercontroller();
List<dynamic> value = await HController.GetHairdressers();
int i = 0;
value.forEach((dynamic entry) {
Hairdresser p = new Hairdresser();
p.name = value[i]["name"];
p.location = value[i]["location"];
this.HairdressersData.add(p);
i++;
});
print("List length iniside the method : "+this.HairdressersData.length.toString());
}
i am calling this method in the initState() :
void initState() {
super.initState();
asyncInitState();
print('data length is '+ this.HairdressersData.length.toString());
}
the problem is thatdata is being added to the list inside the method scoop so the list length is not null however outside the method scope the list is empty.
Your code is correct except, you are printing before asyncInitState executes completely. See Asynchronous Programming
Try
void initState() {
super.initState();
asyncInitState().then((){
print('data length is '+ this.HairdressersData.length.toString());
});
}
Future asyncInitState() async {
Hairdressercontroller HController = Hairdressercontroller();
List<dynamic> value = await HController.GetHairdressers();
int i = 0;
value.forEach((dynamic entry) {
Hairdresser p = new Hairdresser();
p.name = value[i]["name"];
p.location = value[i]["location"];
this.HairdressersData.add(p);
i++;
});
print("List length iniside the method : "+this.HairdressersData.length.toString());
}
Or
void initState() {
testAsyncInitState();
super.initState();
}
void testAsyncInitState() async {
await asyncInitState();
print('data length is '+ this.HairdressersData.length.toString());
}

Flutter, Firestore, how to get each query at the same using await?

What I am trying to do currently is below
//some uid lists..
List<String> uidList;
//some future functions..
List<dynamic> gettingUserFuntions;
void _funA() async{
uidList.forEach((uid) {
gettingUserFunctions.add(_getUser(uid));
});
await Future.wait([
//this gets error
for (var function in gettingUserFunctions)
{
function();
}
]).then((data) {
print("everything completed at sametime!");
});
}
Future<DocumentSnapshot> _getUser(String uid) async {
DocumentSnapshot documentSnapshot =
await FirebaseFirestore.instance.collection('users').doc(uid).get();
return documentSnapshot;
}
For example, suppose that 30 individual documents are each called. I want all of this to be done at the same time. And when everything is done, I want to run the next code.
await Future.wait([]); seems to have a fatal flaw when we don't know the number of functions.
helped from #pskink
void main() async {
var i = [1, 3, 5];
print('start, wait 2 seconds...');
var ret = await Future.wait(i.map(mapper));
print('done $ret');
}
Future mapper(int i) {
print('start future, i: $i');
var d = Duration(milliseconds: 2000 + 200 * i);
return Future.delayed(d, () {
print('future done, i: $i');
return 100 * i;
});
}
Hope this example will help
main() async {
await runFun();
print("runFun end!");
}
runFun() async{
for(int i = 0; i<10; i++){
await waitThreeSec(i);
}
}
waitThreeSec(int i)async{
await Future.delayed(Duration(seconds: 3));
print("$i is done");
}
Output:
0 is done
1 is done
2 is done
3 is done
4 is done
5 is done
6 is done
7 is done
8 is done
9 is done
runFun end!