Flutter Future<void> vs Future<Null> vs void - flutter

What is the main difference between:
Future<void> function(){}
Future<Null> function(){}
void function() {}
funtion(){}
Sometimes I use void or future when calling the API but I don't really know what the main difference is and when is the right time to use it?

Future<void> function() {}
Defines an asynchronous function that ultimately returns nothing but can notify callers when it eventually completes. Also see: What's the difference between returning void vs returning Future?
Future<Null> function() {}
Defines an asynchronous function that ultimately returns null when it eventually completes. Don't use this; this is an archaic form of Future<void>. It predates Dart 2 and was necessary because void was not yet a proper type, and there was no mechanism for indicating that a Future should return nothing. Also see: Dart 2: Legacy of the void
void function() {}
Defines a function that returns nothing. If the function does asynchronous work, callers will not be able to directly tell when it is complete.
function() {}
Defines a function with an unspecified return type. The return type is implicitly dynamic, which means that the function can return anything. Don't do this since it does not convey intent; readers will not be able to tell if the return type was omitted intentionally or accidentally. It also will trigger the always_declare_return_types lint. If you actually want to return a dynamic type, you should explicitly use dynamic function() {} instead.

By default, a function likes function() {} returns a null pointer value.
Use this archetype when your function not return anything and it's not marked as async:
function() { // <- not async
// ... some code
// ... don't use return
}
Optionally, you can specify not return values using void function() {} sintaxis. It's same at the function() {} but if you try to assign a value after calling you will get an error in compile time:
Error: This expression has type 'void' and can't be used.
Personally, i recommend this approach if you really don't have a return value and the function it's not async.
Note that you can use void in normal and async functions.
A function likes Future<void> function() async {} is for asynchronous function thats returns a Future<void> object.
I personally recommend the void function() async {} only if you don't use await ot then on call your function, otherwise, use Future <void> function() async {}.
An examples:
Future<void> myFunction() async {
await Future.delayed(Duration(seconds: 2));
print('Hello');
}
void main() async {
print(myFunction()); // This works and prints
// Instance of '_Future<void>'
// Hello
// Use this approach if you use this:
myFunction().then(() {
print('Then myFunction call ended');
})
// or this
await myFunction();
print('Then myFunction call ended');
}
void myFunction() async {
await Future.delayed(Duration(seconds: 2));
print('Hello');
}
void main() async {
print(myFunction()); // This not works
// The compile fails and show
// Error: This expression has type 'void' and can't be used.
// In this case you only can call myFunction like this
myFunction();
// This doesn't works (Compilation Error)
myFunction().then(() {
print('Then myFunction call ended');
});
// This doesn't works (Compilation Error)
await myFunction();
print('Then myFunction call ended');
}
A function likes Future<Null> function() async {} returns a Future<null> object. Use it whenever you return null. It's not recommended to use it because class Null not extends from Object and anything you return marks an error (except statements thats returns a null or explicit null value):
Future<Null> myFunction() async {
await Future.delayed(Duration(seconds: 2));
print('Hello');
// Ok
return (() => null)();
// Ok
return null;
}

Related

Flutter Riverpod Future provider - requires async and await?

I've been reviewing the RiverPod 2 tutorial at https://codewithandrea.com/articles/flutter-state-management-riverpod/
In the section dealing with Future providers there is a code snippet as shown below...
final weatherFutureProvider = FutureProvider.autoDispose<Weather>((ref) {
// get repository from the provider below
final weatherRepository = ref.watch(weatherRepositoryProvider);
// call method that returns a Future<Weather>
return weatherRepository.getWeather(city: 'London');
});
I can't understand why this code snippet is missing the 'async' and 'await' syntax as shown below...
final weatherFutureProvider = FutureProvider.autoDispose<Weather>((ref) async {
// get repository from the provider below
final weatherRepository = ref.watch(weatherRepositoryProvider);
// call method that returns a Future<Weather>
return await weatherRepository.getWeather(city: 'London');
});
Is my version correct or what?
Think of it as doing:
Future<int> example() {
return Future.value(42);
}
instead of:
Future<int> example() async {
return await Future.value(42);
}
Sure, you can use async/await. But it is technically optional here.
Doing return future vs return await future doesn't change anything. In fact, there's a lint for removing the unnecessary await: unnecessary_await_in_return
The async keyword is generally helpful. It catches exceptions in the function and converts them into a Future.error.
But FutureProvider already takes care of that. So async could also be omitted

How to explicitly return `void`?

One flutter package has this kind of data requesting workflow:
final cancelListening = await request(
query: query,
onResponse: (response) {
streamController.add(response);
cancelListening(); // I need to cancel it here;
},
);
But this way I obviously have the error: cancelListening can't be referenced before it is declared. As request() returns Future<void Function()> I can do this:
void Function() cancelListening = () {};
cancelListening = await request(
...
And I got Omit type annotations for local variables.dart(omit_local_variable_types).
So, I write this way:
var cancelListening = () {}
cancelListening = await request(
...
But now cancelListening is Null Function() and I'm getting A value of type 'void Function()' can't be assigned to a variable of type 'Null Function()'.
So my questions is:
Is there is a way to explicitly return void in dart? Something like () => Void();
Should I simply ignore this linter rule or there is better way to handle this situation?
Thanks.
You might want to setup an intermediary function to call the received callback. VoidCallback should be a type for functions that specifically return void, instead of null.
VoidCallback? cancelListening;
void stopListening() {
cancelListening?.call();
}
void listen() async {
cancelListening = await request(
query: query,
onResponse: (response) {
streamController.add(response);
stopListening();
},
);
}
Optionally, instead of making cancelListening nullable, you could use the late keyword.
late VoidCallback cancelListening;
void stopListening() {
cancelListening(); // No optional operator `?` needed.
}

Is there a difference whether using await with return in Dart?

In my flutter project, say there's a foo(int x) async function. And bar() async that looks like:
Future bar() async {
return foo(3);
}
The bar() function is just a simple capsule for foo(int x) with a certain parameter. And bar() is used as the future in a FutureBuilder.
I'm not sure if I should use await with return. I can't find related documentations online. So what's the difference between return foo(3) and return await foo(3)? Thank you!
No difference whatsoever.
Technically, using await first might wait for the Future to resolve before returning from the function, but you won't be able to tell the difference.
A Future is returned either way.
The async there is useless too, it might as well just be an arrow:
Future bar() => foo(3);
If it were not the last statement, and a return statement, this could matter, as pointed out in the comments, take the following:
Future bar() async {
try {
return await foo(3);
} catch(error) {
return baz;
}
}
If foo rejects, then it matters quite a lot, as it would be handled by the callee, not the caller.
Since you are returning Future, in this exact case, even if you don`t await it, the foo(3) will return Future instead and it is the exact thing your function wants to return. and if u await it there, then it will await in the function and then return the value.
you don`t even need await in this case if foo return Future. Then the caller of bar will instead await the bar.
Using this simple example you can see in which order prints yield:
Future<void> fetchUserOrder() {
return Future.delayed(const Duration(seconds: 2), () => print('Large Latte'));
}
void main() async {
await fetchUserOrder();
print('Fetching user order...');
}
fetchUserOrder() returns Future. So if we call it in main with await, it will receive the Future, execute it and await for the result. Only then proceed to the second print of the main.
We could've written the fetchUserOrder() in such a fashion:
Future<void> fetchUserOrder() async {
return await Future.delayed(const Duration(seconds: 2), () => print('Large Latte'));
}
And it wouldn't have had changed the result. It would work the same, the only difference is shorter code and that now you understand how it works.
Use https://dartpad.dev/ to launch these examples.

Dart Flutter, help me understand futures

See this code:
class SomeClass{
String someVariable;
SomeClass();
Future<String> getData () async {
Response response = await get('http://somewebsite.com/api/content');
Map map = jsonDecode(response.body); // do not worry about statuscode, trying to keep it minimal
someVariable = map['firstName'];
return 'This is the first name : $someVariable';
}
}
Now look at main:
void main(){
String someFunction() async {
SomeClass instance = SomeClass(); // creating object
String firstNameDeclaration = await instance.getData().then((value) => value);
return firstNameDeclaration;
}
}
When working with Future, like in the case of firstNameDeclaration why do I have to use .then() method to access the string object, since I am waiting for the function to finish?
When searching on the web, some people use .then() others don't, I am confused.
Kindly help me have a clearer understanding of how Futures and async functions overall work.
Background
Asynchronous operations let your program complete work while waiting for another operation to finish. Here are some common asynchronous operations:
Fetching data over a network.
Writing to a database.
Reading data from a file.
To perform asynchronous operations in Dart, you can use the Future class and the async and await keywords.
When an async function invokes "await", it is converted into a Future, and placed into the execution queue. When the awaited future is complete, the calling function is marked as ready for execution and it will be resumed at some later point. The important difference is that no Threads need to be paused in this model.
Futures vs async-await
When an async function invokes "await", it is converted into a Future, and placed into the execution queue. When the awaited future is complete, the calling function is marked as ready for execution and it will be resumed at some later point. The important difference is that no Threads need to be paused in this model.
async-await is just a a declarative way to define asynchronous functions and use their results into Future and it provides syntactic sugar that help you write clean code involving Futures.
Consider this dart code snipped involving Futures -
Future<String> getData(int number) {
return Future.delayed(Duration(seconds: 1), () {
return 'this is a future string $number.';
});
}
main(){
getData(10).then((data) => {
print(data)
});
}
As you can see when you use Futures, you can use then callback when the function return a future value. This is easy to manage if there is single "then" callback but the situation escalates quickly as soon as there are many nested "then" callbacks for example -
Future<String> getProductCostForUser() {
return getUser().then((user) => {
var uid = user.id;
return getOrder(uid).then((order) => {
var pid = order.productId;
return getProduct(pid).then((product) => {
return product.totalCost;
});
});
});
}
main(){
getProductCostForUser().then((cost) => {
print(cost);
});
}
As you can when there multiple chained "then" callback the code become very hard to read and manage. This problem is solved by "async-await". Above chained "then" callbacks can be simplified by using "async-await" like so -
Future<String> getProductCostForUser() async {
var user = await getUser();
var order = await getOrder(user.uid);
var product = await getProduct(order.productId);
return product.totalCost;
}
main() async {
var cost = await getProductCostForUser();
print(cost);
}
As you can above code is much more readable and easy to understand when there are chained "then" callbacks.
I hope this explains some basic concepts and understanding regarding the "async-await" and Futures.
You can further read about topic and examples here
Basically, you should either use await OR then(). However, Dart guidelines advocates that you should prefer use await over then() :
This code :
Future<int> countActivePlayers(String teamName) {
return downloadTeam(teamName).then((team) {
if (team == null) return Future.value(0);
return team.roster.then((players) {
return players.where((player) => player.isActive).length;
});
}).catchError((e) {
log.error(e);
return 0;
});
}
should be replaced by :
Future<int> countActivePlayers(String teamName) async {
try {
var team = await downloadTeam(teamName);
if (team == null) return 0;
var players = await team.roster;
return players.where((player) => player.isActive).length;
} catch (e) {
log.error(e);
return 0;
}
}
In your case, you should write :
void main(){
Future<String> someFunction() async {
SomeClass instance = SomeClass(); // creating object
String firstNameDeclaration = await instance.getData();
return firstNameDeclaration;
// Or directly : return await instance.getData();
// Or : return instance.getData();
}
}

Future<void> vs void

Say I want to create an asynchronous method. I can make its return type either Future void or simply "void" (as in examples below). Both ways seem to do the trick. So what's the difference between the two? When should I use Future void instead of void? Thanks!
Future<void> myMethod() async{
await myOtherMethod(); //myOtherMethod() has return type of Future<void>
print('something');
}
vs
void myMethod() async{
await myOtherMethod(); //myOtherMethod() has return type of Future<void>
print('something');
}
Use Future<void> where you want to
Call future functions:
myMethod().then((_) => ...).catchError((err) => ...);
Use await for more readable async code.
await myMethod();
await anotherMethod();
Use void where you want to fire and forget.
myMethod();
... do other stuff
The Future<void> is a lot more common. If you're not sure which one to use, use Future<void>.
Future<void> myMethod() async{ }
is a asynchronous function which means it let the app to work while waiting for some operation to finish(ex:Network Request).The Future fun(); is used while we need to perform operation that gives result in future such as network call.
void fun(){};
is function that doesnot return anything.