What does void Function() do in Dart? - dart

I´m quite new to dart and wondering what this "wrapped" function exactly does?
It´s called like a normal function with "connectUnits(userRepo)":
void Function(
Store<AppState> store,
dynamic action,
NextDispatcher next,
) connectUnits(
UnitsRepository unitsRepository,
) {
return (store, action, next) {
unitsRepository.units().listen((units) {
store.dispatch(LoadUnitsAction(units));
next(action);
});
};
}
Thanks & best,
Michael

Functions are first class citizens in Dart. Your example defines a function named connectUnits that returns a function with a signature void Function(Store<AppState> store, dynamic action, NextDispatcher next).
To better understand, your code is the same as:
// define a kind of function
typedef MyFunction = void Function(Store<AppState> store, dynamic action, NextDispatcher next);
MyFunction connectUnits(UnitsRepository unitsRepository) {
return (store, action, next) {
unitsRepository.units().listen((units) {
store.dispatch(LoadUnitsAction(units));
next(action);
});
};
}

Related

Dart, how to unit test a function with mocking method inside

I want to unit test a function with mocking a function inside.
This is the simplified code I want to test:
import 'package:test/test.dart';
Future<int> function() async {
final int value = await API(); // This returns a int.
return value + 1;
}
void main() {
test('test function, (when api() returns 1)', () {
expect(function(), completion(equals(2)));
});
}
When testing, I don't want to call the real API() function but, want to mock it instead. Is there any solution to this?

Whats the difference about defining a variable as Function or Function() in dart

What's the diference about setting the type of a variable as Function or Function()?
Function function1 = () { print("1"); };
Function() function2 = () { print("2"); };
// Both works
function1();
function2();
The type Function does just say that your variable points to a Function but does not require this variable to point to a function with a specific signature.
Function() actually gives an analyzer warning on my machine because this is not entirely correct. Instead it should have been void Function() function2 = () { print("2"); };. This specifies that function2 must point to a function which does not return anything and takes zero arguments.
The last is also what would be declared by Dart itself if you have used var or final instead of specifying the type.
The difference becomes clear if you change the method to take an argument:
Function function1 = (int a) { print("1"); }; // works
void Function() function2 = (int a) { print("2"); }; // error

How does onTap VoidCallback handler work when it's an async (returning a Future<Null>)?

I'm trying to push a route to display a ListView item when that item is tapped (onTap). The onTap property for InkWell is defined as a VoidCallback. However, I would like to be able to receive a return value from the callback, indicating whether the user has modified said item in the dialog that was opened.
Assigning a Future<Null> async function to onTap seems to be OK, as per the Shrine Demo (shrine_home.dart in the flutter_gallery example):
Future<Null> _showOrderPage(Product product) async {
final Order order = _shoppingCart[product] ?? new Order(product: product);
final Order completedOrder = await Navigator.push(context, new ShrineOrderRoute(
order: order,
builder: (BuildContext context) {
return new OrderPage(
order: order,
products: _products,
shoppingCart: _shoppingCart,
);
}
));
assert(completedOrder.product != null);
if (completedOrder.quantity == 0)
_shoppingCart.remove(completedOrder.product);
}
Why and how is this working? Thanks.
Dart allows you to use a function with a non-void return value as a function with a void return value. The function will still return values as normal, but the analyzer will infer that they're of the void type and will complain if you try to use them, unless you cast them back to something else.
typedef void VoidCallback();
typedef int IntCallback();
final IntCallback i = () => 42;
void main() {
final VoidCallback v = i;
print("${v()}"); // prints 42
print(v() as int); // also prints 42
print(v().toString()); // also prints 42, but analyzer complains:
// method 'toString' isn't defined for class 'void'
}
That is why you can use a function that returns a Future<Null> as a VoidCallback.
Oops. Just realized the assignment was actually via a lambda, which is a VoidCallback:
onPressed: () { _showOrderPage(product); }
Still - it seems to be working for me in another place, where I assign a Future<Null> async function to the onPressed method of FloatingActionButton...

How to store function as class member variable

Is it possible in Dart to store a callback function with return and argument type information? It appears I can do the following:
class MyClass {
void addCallback( callback( int ) )
{
_callback = callback;
}
var _callback;
}
But I thought it would be nice if _callback wasn't declared as var, and instead had information about its return and argument types. I couldn't find info on this in the docs, anyone know?
Dart 2 supports a function type syntax:
class MyClass {
void addCallback( callback( int ) )
{
_callback = callback;
}
void Function(int) _callback;
}
The Effective Dart Design Guide states that this form is preferred over typedefs.
You can typedef a Function signature like this:
typedef bool Filter(num x);
List<num> filterNumbers(List<num> numbers, Filter filter) {
return numbers.where(filter).toList();
}
For more great information like this, check out this article: https://www.dartlang.org/articles/idiomatic-dart/

How return Future from Future? Or this is prohibited in async library?

How I can return Future value from Future object?
This code does not work.
import 'dart:async';
void main() {
var temp = foo();
temp.then((Future<int> future) {
future.then((int result) {
print(result);
});
});
}
Future<Future<int>> foo() {
return new Future<Future<int>>(() {
return new Future<int>(() => 5);
});
}
How to prevent unnecessary unwrapping?
In this case in async library 'Future' declared as generic class.
abstract class Future<T> {
}
If I create expression as the following
new Future<Future<int>>();
Then with type T specified as Future<int> which result expected from generic class Future?
I thing that result must be as specified in type argument T.
I.e. Future<int>.
But result is not as expected.
There is no information found about this abnormal behavior on Dart API site.
If this is a "feature" (but I think that abnormal behavior wrongly to call "feature') then why it not documented in Dart API?
How can be explained this discrepancy?
Why this code not generated errors and warnings?
Another IDENTICAL example but w/o using Future.
void main() {
var temp = foo();
temp.baz((Foo<int> foo) {
foo.baz((int result) {
print(result);
});
});
}
Foo<Foo<int>> foo() {
return new Foo<Foo<int>>(() {
return new Foo<int>(() => 5);
});
}
If in this case result will be as when using Future (i.e. unexpected) then how we can call this code?
Normal or abnormal?
Or maybe the Future in Dart some special (magic)?
Look at the api documentation
http://api.dartlang.org/docs/releases/latest/dart_async/Future.html
It says there:
If the returned value is itself a Future, completion of the created future will wait until
the returned future completes, and will then complete with the same result.
I guess that means you can't return a Future from a Future.
But you could return a list of futures.
void main() {
var temp = foo();
temp.then((List<Future<int>> list) {
list[0].then((int result) {
print(result);
});
});
}
Future<List<Future<int>>> foo() {
return new Future<List<Future<int>>>(() {
return [new Future<int>(() => 5)];
});
}
There is no need for any of that extra wrapping. According to the Future documentation:
If the returned value is itself a [Future], completion of the created
future will wait until the returned future completes, and will then
complete with the same result.
This means you can rewrite your code as:
import 'dart:async';
void main() {
var temp = foo();
temp.then((int result) {
print(result);
});
}
Future<int> foo() {
return new Future<int>(() {
return new Future<int>(() => 5);
});
}
This is a lot cleaner to work with and provides the expected result.

Resources