Here am trying to return a Position type from a function inside a condition statement but am getting a runtime error that the function is not returning a of Position type.
Future<Position> getCurrentDevicePosition(BuildContext context) async {
if (await checkLocationService(context)) {
if (await checkPermission(context) == LocationPermission.always) {
return await Geolocator.getCurrentPosition();
}
}
}
So i solved the problem just by adding "?" to the return type of the function like so but i don't know if that is possible with java too because i had such experience with java and I did not finish it... here is how i did it using Dart in flutter.
Future<Position?> getCurrentDevicePosition(BuildContext context) async {
if ((await checkLocationService(context)) &&
(await checkPermission(context) == LocationPermission.always)) {
return Geolocator.getCurrentPosition();
} else {
errorSnackBar(context, 'Location enable location');
}
return null;
}
Related
I have a problem on my flutter app, when try to load a data from api using dio and this api is private so need to be connected to the same network, so to check everything is fine I tried to connect using mobile data that means dio connection won't success and return timeout, when I call that inside BLoC and use BloCBuilder to build UI depending on state bloc return loadingstate then return errorstate and try to do the event again and fail then repeat this over and over, I just want to avoid this and return error state only and stop listening on that event
void _loadAllSpecialities(
LoadAllSpecialities event, Emitter<DoctorsState> emit) async {
emit(
const DoctorsLoadingState(),
);
emit(const DoctorsLoadingState());
final result = await doctorService.getAllSpeciality(event.jwtToken);
print(result.toString());
//has no error and data loaded
if (result.item1 == null) {
final speicailities = result.item2;
emit(DoctorsSpecialitiesLoaded(specialities: speicailities));
} else {
//has error (error not null)
emit(DoctorErrorState(result.item1!));
}
}```
.
class DoctorService {
final List<DoctorSpeciality> specialities = [];
final options = Options(
responseType: ResponseType.json,
receiveTimeout: 2000,
sendTimeout: 2000,
);
final _dio = Dio();
Future<Tuple<String?, List<DoctorSpeciality>>> getAllSpeciality(
String jwtToken) async {
specialities.clear();
var tuple = Tuple<String?, List<DoctorSpeciality>>(null, []);
try {
final response = await _dio.get<List>(ApiVars.specialitiesEndPoint,
options:
options.copyWith(headers: {"Authorization": "Bearer $jwtToken"}));
if (response.statusCode == 200) {
//has no data
if (response.data == null) {
//set error 1
tuple.setNewValues('No data loaded', []);
//print it
log(tuple.item1 ?? '');
//return tuple with error and empty list
return tuple;
}
//has data then map it into list of specialities
response.data?.forEach((element) {
//convert json to speciality and add it to specialities list
specialities.add(DoctorSpeciality.fromJson(element));
});
//set error to null and list to specialites list
tuple.setNewValues(null, specialities);
return tuple;
} else {
//set error to error with the code and list to empty list
tuple.setNewValues('error occur with code ${response.statusCode}', []);
log(tuple.item1 ?? '');
return tuple;
}
} on DioError catch (error) {
//set error to error message and list to empty list
tuple.setNewValues("doc service ${error.message}", []);
log(tuple.item1 ?? '');
return tuple;
}
}
}
I tried add droppable, sequential and didn't work
on<LoadAllSpecialities>(_loadAllSpecialities, transformer: droppable());
I solved the problem by adding Future before function that called inside the handler function and await it to end as code in below
///constructor called super and pass initial state...
on<DoctorsEvent>(
(event, emit) async {
try {
if (event is LoadAllSpecialities) {
// * load all specialities of doctors from api ...
//add await here
await _loadAllSpecialities(event, emit);
}
} catch (error) {
emit(DoctorErrorState(error.toString()));
}
},
);
}
//add future here
Future<void> _loadAllSpecialities(
LoadAllSpecialities event, Emitter<DoctorsState> emit) async {
emit(
const DoctorsLoadingState(),
);
emit(const DoctorsLoadingState());
final result = await doctorService.getAllSpeciality(event.jwtToken);
//has no error and data loaded
if (result.item1 == null) {
final speicailities = result.item2;
emit(DoctorsSpecialitiesLoaded(specialities: speicailities));
} else {
//has error (error not null)
emit(DoctorErrorState(result.item1!));
}
}
I'm new on the Flutter & working on the integration of POS printing machine in flutter & using the pos_printer_manager package.
It shows an error in the catch part of this package i.e.
type 'Future<bool?>' is not a subtype of type 'FutureOr<bool>' in type cast
& pointing out in this code
/// [writeBytes] let you write raw list int data into socket
#override
Future<ConnectionResponse> writeBytes(List<int> data,
{bool isDisconnect: true}) async {
try {
if (!isConnected) {
await connect();
}
if (Platform.isAndroid || Platform.isIOS) {
if ((await (bluetooth.isConnected as FutureOr<bool>))) {
Uint8List message = Uint8List.fromList(data);
PosPrinterManager.logger.warning("message.length ${message.length}");
await bluetooth.writeBytes(message);
if (isDisconnect) {
await disconnect();
}
return ConnectionResponse.success;
}
return ConnectionResponse.printerNotConnected;
}
// else if (Platform.isIOS) {
// // var services = (await fbdevice.discoverServices());
// // var service = services.firstWhere((e) => e.isPrimary);
// // var charactor =
// // service.characteristics.firstWhere((e) => e.properties.write);
// // await charactor?.write(data, withoutResponse: true);
// return ConnectionResponse.success;
// }
return ConnectionResponse.unsupport;
} catch (e) {
print("Error : $e");
return ConnectionResponse.unknown;
}
}
This is due to bluetooth.isConnected as FutureOr<bool>.
So any big difference between Future<bool?> & FutureOr<bool> ?
Basically I faced type casting error in the package & I need a solution to handle this on the package side & how to manage the optional.
Based on your findings typecast is not required, it requires a null check
change this it to
if (Platform.isAndroid || Platform.isIOS) {
bool? isConnected = await bluetooth.isConnected;
if (isConnected != null && isConnected!) {
Uint8List message = Uint8List.fromList(data);
PosPrinterManager.logger.warning("message.length ${message.length}");
await bluetooth.writeBytes(message);
if (isDisconnect) {
await disconnect();
}
return ConnectionResponse.success;
}
return ConnectionResponse.printerNotConnected;
}
Resolved it by a simple check:
bool? btConnected = await bluetooth.isConnected ?? false;
I have this Future and my code template like this:
Future getDevices() async {
stream.listen();
Timer.periodic(Duration(seconds:5), (timer) {
POST TO SERVER.then((value){
return Future.value(value);
});
});
}
I'm Listening to a Stream to scan for beacon devices.
I fill the yield named "beacons" in the Listen function of this Stream.
With Timer.periodic, I control the yield named "beacons" and perform POST operation. I want to return Future.value on "then" of this POST operation. But Future returns null without waiting for the result of POST operation.
I tried Completer like this:
Future getDevices() async {
final completer = Completer();
stream.listen();
Timer.periodic(Duration(seconds:5), (timer) {
POST TO SERVER.then((value){
return completer.complete(value);
});
});
return completer.future;
}
but this time I also got this error: "Unhandled Exception: Bad state: Future already completed"
EDIT:
I try to use Stream.asyncMap but same result when i did it.
Stream myStream = Stream.periodic(Duration(seconds: 5), (timer) async {
beacons.removeWhere((key, value) =>
DateTime.now().difference(value['lastUpdate']).inSeconds > 6);
if (beacons.isNotEmpty) {
bool processResult = false;
beacons.forEach((key, value) async {
if (int.parse(value['onlyEnterance'].toString()) == 1 &&
double.parse(value['distance'].toString()) <
double.parse(value['minDistance'].toString())) {
await userRepo
.createPayrollTracking(context, forEnter, value['dbId'])
.then((value) {
processResult = value;
if (value == true) {
stopMonitoring();
}
});
return await Future.value(processResult);
}
});
}
}).asyncMap((event) async => await event);
I'm new to flutter, I just want to ensure if the below code is correct, I want to check if the location permission was granted or no, if yes then get the current location and save into shared preferences and THEN go to the homepage route, otherwise go to the location page to ask the user for access his location
#override
void initState() {
super.initState();
checkLocation(context);
}
void checkLocation(context) async {
bool isGranted = await asyncFunction();
if(isGranted)
{
updateSettingLocation();
Navigator.of(context).pushNamed('/homepage');
} else{
Navigator.of(context).pushNamed('/location');
}
}
void updateSettingLocation() async{
final location = await currentLocation();
settingsRepo.setCurrentLocation(location);
}
Future<Position> currentLocation() {
return Geolocator.getCurrentPosition(desiredAccuracy: LocationAccuracy.high)
.then((location) {
if (location != null) {
print("Location: ${location.latitude},${location.longitude}");
}
return location;
});
}
void updateCurrentLocation() async {
Position position = await Geolocator.getCurrentPosition(
desiredAccuracy: LocationAccuracy.high);
settingsRepo.setCurrentLocation(position);
}
Future<bool> asyncFunction() async {
bool serviceEnabled;
LocationPermission permission;
permission = await Geolocator.checkPermission();
serviceEnabled = await Geolocator.isLocationServiceEnabled();
if (permission == LocationPermission.denied || !serviceEnabled || permission == LocationPermission.deniedForever) {
print('location access is denied');
return false;
} else {
print('location access is granted');
return true;
}
}
As mentioned in this Stack Overflow answer , the following changes should sufficient
#override
void initState() {
super.initState();
WidgetsBinding.instance.addPostFrameCallback((_) => checkLocation(context));
}
Though I would like to point out that context is not available in initState (unless it's a variable that you've created and are managing)
All the functions defined are correct and the methodology is also fine. It should work with no issues. However I would suggest instead of defining all the functions here in the widget class you should separate it out from the UI by creating a separate class (Example: LocationService) and then initialize that class here and then make use of the functions.
I am running sonarqube and fixing the errors. Actually most of the async methods which we used in our project we are returning void. But in the sonar report it is throwing error that it should return Task instead of void. When I changed the void to Task and executed sonar it is throwing error as "the method has the wron return type.
Can anybody please help me on this.
private async void OnNextBtnClick()
{
try
{
if (condition)
{
await Task.Delay(100);
_loadingService.ShowProgressBar();
if (_connectionService.CheckOnline())
{
fun();
CreatedTransactionRequest request =
new CreatedTransactionRequest
{
--------------------------
};
var response = await _orderDataService.GetCreatedTransactionDetails(request).ConfigureAwait(false);
var navFlag = HandleNavigationBasedOnResponse(response);
if (navFlag == Convert.ToInt16(NavigationType.CreateDropOff))
{
ShowScheduleDropOneScreen();
_loadingService.HideProgressBar();
}
else if (navFlag == Convert.ToInt16(NavigationType.DropOffDialog))
{
ShowDropoffDialogScreen();
_loadingService.HideProgressBar();
}
else if (navFlag == Convert.ToInt16(NavigationType.TransactionDialog))
{
ShowTransactionDialogScreen();
_loadingService.HideProgressBar();
}
}
else
{
_loadingService.HideProgressBar();
await _dialogService.ShowAlertAsync(TextSource.GetText("NetworkError"), TextSource.GetText("Error"),
TextSource.GetText("ok"),
Constants.AlertType.Error).ConfigureAwait(false);
}
}
else
{
----------------------------------
}
}
catch (Exception ex)
{
_loadingService.HideProgressBar();
await _exceptionHandlerService.HandleErrorAsync(ex).ConfigureAwait(false);
}
}
Well from my understanding of the situation you are trying to convert a void method to Task it's very easy without any change of code
Something like this :
private async Task yourMehtod()
{
await Task.Factory.StartNew(async() => { await yourVoidMethod(); });
}