Say I have:
void main() async{
Future<void> ValueChanged<int> onPressed; // error
await onPressed(10); // wanna use something like this
}
So, what's the solution now?
Create your own typedef:
typedef MyValueChanged<P, Q> = Future<Q> Function(P value);
And now use it like:
void main() async{
MyValueChanged<int, void> onPressed;
await onPressed(10); // no errors
}
Related
when I run the below code snippet,I can't "Your order is: Large Latte".Instead I get "Your order is: Instance of '_Future".So what am I doing wrong?
Future<String> createOrderMessage() async{
var order = await fetchUserOrder();
return 'Your order is: $order';
}
Future<String> fetchUserOrder() =>
Future.delayed(
const Duration(seconds: 2),
() => 'Large Latte',
);
void main() {
print(createOrderMessage());
}
You have to await the first method call. So change to this:
void main() async {
print(await createOrderMessage());
}
If not, the main method will not wait for the Future to complete and instead just print that createOrderMessage() is an instance of a Future.
In this article, they spawned an isolate like this:
import 'dart:isolate';
void main() async {
final receivePort = ReceivePort();
final isolate = await Isolate.spawn(
downloadAndCompressTheInternet,
receivePort.sendPort,
);
receivePort.listen((message) {
print(message);
receivePort.close();
isolate.kill();
});
}
void downloadAndCompressTheInternet(SendPort sendPort) {
sendPort.send(42);
}
But I can only pass in the receive port. How do I pass in other arguments?
I found an answer so I'm posting it below.
Since you can only pass in a single parameter, you can make the parameter a list or a map. One of the elements is the SendPort, the other items are the arguments you want to give the function:
Future<void> main() async {
final receivePort = ReceivePort();
final isolate = await Isolate.spawn(
downloadAndCompressTheInternet,
[receivePort.sendPort, 3],
);
receivePort.listen((message) {
print(message);
receivePort.close();
isolate.kill();
});
}
void downloadAndCompressTheInternet(List<Object> arguments) {
SendPort sendPort = arguments[0];
int number = arguments[1];
sendPort.send(42 + number);
}
You've lost type safety like this, but you can check the type in the method as needed.
We can get back the type safety by creating a custom class with fields
class RequiredArgs {
final SendPort sendPort;
final int id;
final String name;
RequiredArgs(this.sendPort, this.id, this.name);
}
void downloadAndCompressTheInternet(RequiredArgs args) {
final sendPort = args.sendPort;
final id = args.id;
final name = args.name;
sendPort.send("Hello $id:$name");
}
Code will be much cleaner and safer in this way 🥸
I am trying to add the content of directory using this approach and asign it to List but not sure why it's not working. I see it's async problem but not sure how to solve it.I expect to return the list of files from retCont() but instead it's returning empty list.
import 'dart:io';
void main() async {
print('CONT: ${await retCont()}');
}
Future retCont() async {
var myDir = Directory.current;
List cont = [];
await myDir.list().listen((FileSystemEntity entity) {
print(entity.path);
cont.add(entity.path);
});
return cont;
}
listen() returns a StreamSubscription<FileSystemEntity> which is not a Future so you cannot await on that.
The list() call returns Stream<FileSystemEntity>. For streams you can instead of await and listen() use await for like this:
import 'dart:io';
Future<void> main() async {
print('CONT: ${await retCont()}');
}
Future<List<String>> retCont() async {
final myDir = Directory.current;
final cont = <String>[];
await for (final entity in myDir.list()) {
print(entity.path);
cont.add(entity.path);
}
return cont;
}
And as a bonus fact, the same program can be written like this if you skip the print(entity.path);.
import 'dart:io';
Future<void> main() async {
print('CONT: ${await retCont()}');
}
Future<List<String>> retCont() =>
Directory.current.list().map((event) => event.path).toList();
If you really want to use StreamSubscription I think the easiest way is to use a Completer instance which you can complete when you have got all the elements from List():
import 'dart:async';
import 'dart:io';
Future<void> main() async {
print('CONT: ${await retCont()}');
}
Future<List<String>> retCont() {
final myDir = Directory.current;
final cont = <String>[];
final completer = Completer<List<String>>();
myDir.list().listen((FileSystemEntity entity) {
print(entity.path);
cont.add(entity.path);
}, onDone: () => completer.complete(cont));
return completer.future;
}
import 'dart:io';
void main() {
performTask();
}
void performTask() {
task1();
task2();
task3();
}
void task1() {
print('task1');
}
void task2() {
Duration timeDuration = Duration(seconds: 3);
sleep(timeDuration);
print('task2');
}
void task3() {
print('task3');
}
After executing first function that is task1() it throws an error:
Uncaught Error: Unsupported operation: ProcessUtils._sleep
I just hit the same roadblock! Not sure how to get sleep to work, but i found that using async/await is a bit more predictable:
// Unused import
// import 'dart:io'; // Delete me
void main() {
performTask();
}
// No need for async/await here, just the method in which it's used to await Future.delayed
void performTask() {
task1();
task2();
task3();
}
void task1() {
print('task1');
}
// I'm still a bit new to flutter, but as I understand it, best practice is to use Future<T> myFunction() {...} when defining async/await method.
// In this case <T> is <void> because you're not returning anything!
Future<void> task2() async {
Duration timeDuration = Duration(seconds: 3);
// sleep(timeDuration) // Delete Me
await Future.duration(timeDuration); // replacement for the sleep method, comes from the 'package:flutter/material.dart'
print('task2');
}
void task3() {
print('task3');
}
Credit: How can I "sleep" a Dart program
Since Future.duration doesn't
await Future.delayed(const Duration(seconds: 1));
credit: How can I "sleep" a Dart program
I'm new to both Flutter and Dart, and I'm trying to use the Camera Plugin to understand how things work. All examples I find have this part:
List<CameraDescription> cameras;
Future<Null> main() async {
cameras = await availableCameras();
runApp(new CameraApp());
}
Is there some way I could do this inside the initState() method? I guess this is also a more general question regarding async work required before the initState-method is run. (As the initState-method cannot be async).
My goal is to create a StatefulWidget containing a feed from the camera, that is used from another file. Here's what I have so far. Any help appreciated!
List<CameraDescription> cameras;
#override
void initState() {
super.initState();
getCameras();
controller = new CameraController(cameras[0], ResolutionPreset.medium);
controller.initialize().then( (_) {
if (!mounted) {
return;
}
setState(() {});
});
}
Future<Null> getCameras() async {
cameras = await availableCameras();
}
You can't do async work in initState, but you can kick-off async work done in other functions, and then signal when you are done with a setState call. Using await you can make sure the cameras and controller are setup in the correct order. calling setState at the end will make sure the widget gets rebuilt at the end, where you can pass your initialized camera controller wherever you want.
class _CameraState extends State<CameraWidget> {
List<CameraDescription> cameras;
CameraController controller;
bool _isReady = false;
#override
void initState() {
super.initState();
_setupCameras();
}
Future<void> _setupCameras() async {
try {
// initialize cameras.
cameras = await availableCameras();
// initialize camera controllers.
controller = new CameraController(cameras[0], ResolutionPreset.medium);
await controller.initialize();
} on CameraException catch (_) {
// do something on error.
}
if (!mounted) return;
setState(() {
_isReady = true;
});
}
Widget build(BuildContext context) {
if (!_isReady) return new Container();
return ...
}
}
You also want to make sure you handle any errors, the package includes a CameraException which is thrown when the platform specific code fails.