Flutter null safety: Error: A value must be explicitly returned from a non-void function - flutter

Future<void> saveEverything() {
_formKeyForDeposit.currentState?.save();
Navigator.of(this.context).pop(true);
return;
}
This^ is throwing the error:
A value must be explicitly returned from a non-void function.
I've tried returning void, I've tried return true, I've tried returning Future<void>, I've tried returning the Navigator.pop line.
There is an answer on Stackoverflow, but that doesn't work with enforced null safety, this function wants something returned despite being void. I don't understand it.
It won't compile, I'd love some clarity on what drives the issue, and a solution.

As far as I can see none of the called functions are async, so there is nothing you could await. This means that your function isn't asynchronous either and there is no need to use Future as a return type. void should work fine:
void saveEverything() {
_formKeyForDeposit.currentState?.save();
Navigator.of(this.context).pop(true);
}
Edit: To specifically answer:
this function wants something returned despite being void
The return type isn't void, it is a Future with a generic type of void . Future is a normal class and thus your method expects an object of type Future to be returned. The void here is defining what type the value of a successfully resolved Future should have.

like this
Future<void> saveEverything() async {
_formKeyForDeposit.currentState?.save();
Navigator.of(this.context).pop(true);
}

Related

This 'onError' handler must return a value assignable to 'ShortDynamicLink', but ends without returning a value [duplicate]

I have some code like this:
File("foo.txt").readAsString().catchError((e)=>print(e));
The compiler is complaining
info: The return type 'void' isn't assignable to 'FutureOr<T>', as required by 'Future.catchError'.
I can't seem to give it what it wants and can't find a single clear usage example in any of the docs (just a long issue in git about how many ways there are to mis-use this). If I take the docs at face value, I should be able to return a bool, or a future, neither make the analyzer happy.
How do I provide this FutureOr?
The documentation for Future.catchError could be a lot clearer, but the relevant part is:
onError is called with the error and possibly stack trace, and the returned future is completed with the result of this call in exactly the same way as for then's onError.
Cross-referencing to the documentation for Future.then, the relevant portion is:
The onError callback must return a value or future that can be used to complete the returned future, so it must be something assignable to FutureOr<R>.
Since File.readAsString returns a Future<String>, your catchError callback also must return a Future<String>. Examples of doing that:
File("foo.txt").readAsString().catchError((e) {
print(e);
return Future.value('');
});
File("foo.txt").readAsString().catchError((e) async {
print(e);
return '';
});
Logically, this makes sense; because given:
String value = await File("foo.txt").readAsString().catchError(...);
then if readAsString succeeds, value should be assigned a String. If it fails, since you catch the exception without rethrowing it, value still needs to be assigned a String.
Put another way, your code is equivalent to:
Future<String> readFoo() async {
try {
return await File("foo.txt").readAsString();
} catch (e) {
print(e);
}
// Oops, missing return value.
}
In general, I strongly recommend using async/await with try-catch instead of using .catchError, which would avoid this confusion.

The error handler of Future.catchError must return a value of the future's type [duplicate]

I have some code like this:
File("foo.txt").readAsString().catchError((e)=>print(e));
The compiler is complaining
info: The return type 'void' isn't assignable to 'FutureOr<T>', as required by 'Future.catchError'.
I can't seem to give it what it wants and can't find a single clear usage example in any of the docs (just a long issue in git about how many ways there are to mis-use this). If I take the docs at face value, I should be able to return a bool, or a future, neither make the analyzer happy.
How do I provide this FutureOr?
The documentation for Future.catchError could be a lot clearer, but the relevant part is:
onError is called with the error and possibly stack trace, and the returned future is completed with the result of this call in exactly the same way as for then's onError.
Cross-referencing to the documentation for Future.then, the relevant portion is:
The onError callback must return a value or future that can be used to complete the returned future, so it must be something assignable to FutureOr<R>.
Since File.readAsString returns a Future<String>, your catchError callback also must return a Future<String>. Examples of doing that:
File("foo.txt").readAsString().catchError((e) {
print(e);
return Future.value('');
});
File("foo.txt").readAsString().catchError((e) async {
print(e);
return '';
});
Logically, this makes sense; because given:
String value = await File("foo.txt").readAsString().catchError(...);
then if readAsString succeeds, value should be assigned a String. If it fails, since you catch the exception without rethrowing it, value still needs to be assigned a String.
Put another way, your code is equivalent to:
Future<String> readFoo() async {
try {
return await File("foo.txt").readAsString();
} catch (e) {
print(e);
}
// Oops, missing return value.
}
In general, I strongly recommend using async/await with try-catch instead of using .catchError, which would avoid this confusion.

Can't assign non-nullable type to a nullable one

error: The argument type 'Future<List<GalleryPictureInfo>>' can't be assigned to the parameter type 'Future<List<GalleryPictureInfo>>?'.
Is this Dart Analysis or me? The project still compiles.
Upd. Added code example
FutureBuilder<List<GalleryPictureInfo>>(
future: derpiService.getListOfImages(),
//other code
);
#override
Future<List<GalleryPictureInfo>> getListOfImages(arguments) async {
List<GalleryPictureInfo> listOfImages = [];
var searchImages = await getSearchImages(tags: tags, page: page);
//adding images to List
return listOfImages;
}
It's something with FutureBuilder actually. I should've mention this.
Upd. "Fixed" with // ignore: argument_type_not_assignable
Looks like a problem with Dart Analysis for now
Upd. Error
It actually is an error which is pretty self explanatory.
The acutal error comes because of null safety in dart.
For ex:
void main(){
var number = getNumber(true);
int parsedNumber = int.parse(number);
print(parsedNumber);
}
String? getNumber(boolean value) {
if (value){
return null;
} else return "1";
}
So here, getNumber function either returns null or "1" depending upon the value of value variable. So, number variable's type is String?.
But the error shall arise in the next line when you try to call int.parse(). int.parse function takes an argument which should be a String but the value passed in the function is of type String?. So if we pass null in int.parse it shall throw an error.
That's why Dart analysis makes it easier to identify such cases by telling us that the value can be null and it might throw.
However the code depends upon your actual code of your project. It says that you are passing Future<List<GalleryPictureInfo>>? which is of nullable type to a function which requires Future<List<GalleryPictureInfo>>. So, before passing the value you might want to check if the value you are passing is not null.
If you are sure that the value can never be null then if for ex: if you are passing a variable called value, you might wanna try someFunctionWhereYouPassValue(value!)
That ! means that you are sure that the value will never be null.
For more details about null safety you can see:
https://dart.dev/null-safety/understanding-null-safety

Call _method not producing result Flutter

The issue seems to be around calling a method with a _ before it, such as Future _showFirstPolylineMapMarkers
In my main.dart at the end of a method I call 2 entities, one is within main.dart and works fine, the other is in another Class, _mapItemsExample2.
...
_sendIntermodalDataToSecondScreen(context, mappedValues, dest); //works fine
_mapItemsExample2?.getroute(deplat, deplong, deplocname);
}
});
}
It will pass data to
Future getroute(deplat, deplong, deplocname) async {
print('getroutetest');
_showFirstPolylineMapMarkers(deplat, deplong, deplocname);
}
void _showFirstPolylineMapMarkers(deplat, deplong, deplocname) async {
...
But it goes dead and doesn't print or call _showFirstPolylineMapMarkers
If i replace .getroute... with ._showFirstPolylineMapMarkers(deplat, deplong, deplocname) to call the method directly it shows an error
The method '_showFirstPolylineMapMarkers' isn't defined for the type 'MapItemsExample2'.
If i remove the underscore at the start _ errors go away but it doesnt call it when ran
Any guidance appreciated
Thank you
The _ indicates a private field or method, meaning that it can only be used within the file it's defined in.
It is a good practice to use the _ to make methods private to ensure they're only used where they are defined.

Is there a SynchronousFuture equivalent of `async`

For some reason the compiler is complaining about this:
SynchronousFuture<void> setNewRoutePath(AppLink newLink) {
_currentLink = newLink;
// return null; // compiler really wants to see this null return...why?
}
But is happy with this:
Future<void> setNewRoutePath(AppLink newLink) async {
_currentLink = newLink;
}
Seems like async keyword is handling the implicit return here. Is there some equivalent for SynchronousFuture?
SynchronousFuture<void> setNewRoutePath(AppLink newLink) {
_currentLink = newLink;
// return null; // compiler really wants to see this null return...why?
}
You need a return value because your function is declared to return a non-void value, so it must return something. You could argue that all functions could implicitly return null if there's no explicit return statement, but that would be error-prone:
int f(String someValue) {
if (someCondition) {
return 42;
}
} // f didn't return anything if someCondition is false. Accidental or intentional?
Futures themselves aren't really special. If you have a non-async function that returns a Future, you must still have an explicit return statement:
Future<void> f() {
print('Hello world!');
} // Error: f doesn't end with a return statement.
However, the async keyword does a few things:
Primarily it enables the use of the await keyword.
It automatically wraps returned values in a Future. This includes implicit return values from void functions.
SynchronousFuture is just an ordinary class provided by Flutter that implements the Future interface. It is not special. It's not part of the Dart language, so there is not going to be any keyword that does automatic return value wrapping like what the async keyword does.
Also note that you should not just sprinkle return null statements in your function that returns SynchronousFuture. With an async function, a return; statement (or exiting the function without an explicit return statement) ultimately returns a Future<void>() to the caller. Callers expect to be able to call methods (e.g. .then()) on the returned Future to add completion callbacks. If you return null for a SynchronousFuture, calling .then() on it will result in a null pointer exception at runtime. You instead would need to use return SynchronousFuture<void>(null);.
I also should point out that the SynchronousFuture documentation states:
In general use of this class should be avoided as it is very difficult to debug such bimodal behavior.
so unless you have some clear need to use a SynchronousFuture, you're better off avoiding it.
Unless you have created a class called SynchronousFuture the compiler will complain as there is no class called SynchronousFuture in the dart standard library, so either you or a library you import must define this class.
In dart all async functions must have a return value of type Future<T>.
// return null; // compiler really wants to see this null
return...why?
Because Future is not the same as void, when you return a value in an async function, that value is subsequently used as value for the future, as future is a generic class.