Flutter Getx Get.back() not returning value when used along with async function - flutter

I am using Getx package and I want to return a value using Get.back(result: getPhoneNumber()). But Get.back() does not work if an async function is executed before it. Below is the code snippet where handleResponse() is an async function. In addition to this, I have added a print statement to check the value of isSuccessful variable. the value it returns is true.
handleResponse async function:
In addition to this, I would like to state that when I comment the ResponseHandler().handleResponse() function, it works fine as expected.

What happens here is that the back() method seems to finish while getPhoneNumber() is yet to finish. The value passed in return is nullable, and most likely gets a null value since getPhoneNumber() is yet to finish.
What you can do here is first fetch the value from getPhoneNumber() before calling back().
var phoneNumber = await getPhoneNumber();
if(isSuccessful && phoneNumber != null){
Get.back(result: phoneNumber);
}

Related

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.

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

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);
}

How to test a void function in Dart?

I am new to unit tests in Dart/Flutter and I would like to write a test for a void function. When functions return something I am writing a test like this:
test('Gets user save', () async {
final userSave = await mockSource!.getUserSave();
expect(userSave!.age, equals(20));
});
In such a scenario like above expect can be used since getUserSave function returns a user model.
How about checking if test passes of fails for a void/Future function like below? I can not use expect because it does not return a value.
Future<void> clearUserSave() async {
DatabaseClient mockDBClient = MockDatabaseClientImpl();
mockDBClient.clear();
}
I use flutter_test and mockito for testing.
Typically a void function will produce a side effect of some sort. When writing a test for a void function, I would check whatever state is effected by the void function before and after calling the function to be sure that the desired side effect has occurred.
In this specific case, you are calling clear on a DatabaseClient. I don't know the specifics of the DatabaseClient api, but I would construct a test where the client contains some data before calling clear, and then check that the data is no longer there after calling clear.
Something along the lines of this:
Future<void> clearUserSave() async {
DatabaseClient mockDBClient = MockDatabaseClientImpl();
mockDBClient.add(SOMEDATA);
expect(mockDBClient.hasData, true);
mockDBClient.clear();
expect(mockDBClient.hasData, false);
}
you can add nullable variable and assign variable value in method, after call method check if this varaible isNotNull
like this:
test('Gets user save', () async {
await mockSource?.getUserSave();
final userSave=mockSource.user;
expect(userSave,isNotNull );
});
testing a function that return void :
expect(
() async => await functionThatReturnsVoid(),
isA<void>(),
);

Why can't I use local variable in a callback?

Let's say I've a stream() which returns Stream<int>. stream().listen returns StreamSubscription.
var subs = stream().listen((e) {
if (someCondition) subs.cancel(); // Error
});
I don't understand why is there an error, because by the time I start listening for events in the listen method, I would have definitely a valid object subs.
Note: I know this can be done by creating a StreamSubscription instance/top-level variable but why they have prevented the use of local variable like this?
We know that Stream.listen does not call its callback until after a value is returned, but the Dart compiler does not.
Consider the following function, which simply calls a callback and returns the result:
T execute<T>(T Function() callback) => callback();
Now, consider using it to assign a variable:
int myVariable = execute(() => myVariable + 1);
The problem here is that the given callback is called synchronously, before myVariable is assigned, but it tries to use myVariable to calculate a value!
To resolve this issue with your stream question, you can use the new late keyword. Using late tells the compiler that you know the variable will be assigned by the time it's accessed.
late final StreamSubscription<MyType> subscription;
subscription = stream().listen(/* ... */);
Likely because it's possible that subs will be used before it's assigned. We know that the callback passed to listen will be called on stream events, but it's also possible that the callback is called immediately and it's return value or a calculation done by it may be required for the return value of the function it was passed to.
Take this fakeFunc for instance, which I made an extension on the int class for convenience:
extension FakeListen on int {
int fakeFunc(int Function(int x) callback, int val) {
return callback(val);
}
}
The return value depends on the result of callback!
int subs = x.fakeFunc((e) {
print(e);
subs.toString();//error
return e + 1;
}, 5);
I can't use subs because subs will be guaranteed to not be exist at this point. It's not declared. This can be easily solved by moving the declaration to a separate line, but also forces you to make it nullable. Using late here won't even help, because subs won't exist by the time you try to use it in the callback.
Your scenario is different, but this is an example of where allowing that would fail. Your scenario involves a callback that is called asynchronously, so there shouldn't be any issues with using subs in the callback, but the analyzer doesn't know that. Even async-marked methods could have this issue as async methods run synchronously up until its first await. It's up to the programmer to make the right decision, and my guess is that this error is to prevent programmers from making mistakes.