Is it safe to use print() with dart? - flutter

Is it safe to still use print() in dart (flutter 2.5.1), if not what command should I use to print errors?
if (query != null) {
_query.addAll(query);
}
return await dio.get(_url, queryParameters: _query);
} on DioError catch (e) {
print('DioError:$e');
}

What you are getting is just a warning. You should throw errors instead of printing it.
if (query != null) {
_query.addAll(query);
}
return await dio.get(_url, queryParameters: _query);
} on DioError catch (e) {
throw Exception(e);
}

If you're inside a widget ,
Use debugPrint('data') , because it'll only show data in debug mode and will not run in release mode. So, it'll save you a lot of time.
Otherwise , you can also use log('data') , it'll show whole response in logging pattern in console.

Related

Flutter Chrome Debugging: API calls don't work at all

I'm developing a simple web/Android Flutter App. Everything works fine on Android, but when I try debugging it on Chrome (web-javascript), none of my API calls work.
Debugger stops in ticker.dart > TickerFuture > _complete() and this message appears in the console, and the API call continues forever.
ChromeProxyService: Failed to evaluate expression '_primaryCompleter'
I've tried using CORS and try catch blocks to see if i can get more info about the error.
This is an example API call:
Future<bool> login(LoginData l) async {
try {
Uri url = Uri.parse(baseUrl + "/login/");
final response = await http.post(url,
body: {"email": l.name, "password": l.password},
headers: {"Access-Control-Allow-Origin": "*"});
if (response.statusCode == 200) {
return response.body == "true";
} else {
throw Exception('Failed to load books');
}
} catch (e) {
print(e);
throw Exception('Failed to load books');
}
}
There were some issues with debugging in Chrome after Chrome v100 released.
Flutter 2.10.5 was released to fix some of these issues:
https://github.com/flutter/flutter/wiki/Hotfixes-to-the-Stable-Channel#2105-april-18-2022
flutter/101224 - Flutter web debugger fails when using chrome 100 or greater.

why the dart function did not return the sub function result

I am now using this functon to fetch new music in flutter:
class QuietPlayQueueInterceptor extends PlayQueueInterceptor {
#override
Future<List<MusicMetadata>> fetchMoreMusic(BackgroundPlayQueue queue, PlayMode playMode) async {
if (queue.queueId == kFmPlayQueueId) {
final musics = await (neteaseRepository!.getPersonalFmMusicsFromQueue() as FutureOr<List<Music>>);
final musicListExt= musics.toMetadataList();
return musicListExt;
}
return super.fetchMoreMusic(queue, playMode);
}
}
and this is the function getPersonalFmMusicsFromQueue define:
Future<List<Music>?> getPersonalFmMusicsFromQueue() async {
if(fmPlayQueue.isEmpty){
return getPersonalFmMusics();
}else{
final Music music = fmPlayQueue.first;
final List<Music> musics = List.empty(growable: true);
musics.add(music);
return Future.value(musics);
}
}
what makes me confusing is that the getPersonalFmMusicsFromQueue function did not return any result. I make a breakpoint on the line final musicListExt= musics.toMetadataList(); but did not hited. The console is no error output. where am I doing wrong? what should I do to fix this problem?
getPersonalFmMusics looks asynchronous? Perhaps you're not awaiting
Future<List<Music>?> getPersonalFmMusicsFromQueue() async {
if(fmPlayQueue.isEmpty){
return await getPersonalFmMusics();
}
// ...
I would also advise against casting unless you're sure you need it. Instead, have the return type of getPersonalFmMusicsFromQueue return a FutureOr
(neteaseRepository!.getPersonalFmMusicsFromQueue() as FutureOr<List<Music>>); // Remove FutureOr<List<Music>>
// and make the function signature instead look like this:
FutureOr<List<Music>> getPersonalFmMusicsFromQueue(); // Force unwrapping with a `!` but also throwing proper exceptions when null.
The reason being is that casting usually hides errors the compiler would otherwise be warning you about.
Another idea I have if the above isn't the issue is the .first call.
final Music music = fmPlayQueue.first;
If this is a first getter on a stream then that need to be awaited and it likely isn't working because it's just indefinitely waiting for the stream to output a value.

How to prevent flutter app from crashing after Dio error?

I am using the flutter-dio package to make HTTP requests and have made a wrapper on it from my convenience like so
Future<dynamic> post(String uri, dynamic body, {String authKeyCust}) async {
authKey = await SecureStorage.getAuthKey();
try {
Response response = await dio.post(
uri,
data: body,
options: Options(headers: {"authkey": authKeyCust ?? "$authKey"}),
);
return response.data;
} on DioError catch (error) {
print('error: $error');
} on SocketException catch(error) {
print('No net');
}
}
All I want is the app to not crash/pause on exception when any error occurs.
I also had the same problem.
First, try to run it from command prompt with flutter run see if there is occurring any problem or not.
If the command prompt is showing no problem & your app is running smoothly then you have to check the IDE. If you are using VSCode then switch to Debug is side bar, see which options are ticked in Breakpoint section.
If All Exceptions is ticked then the debugger will pause on every exception. Uncheck both All Exceptions & Uncaught Exceptions then try refresh restart.
Hope this will solve your problem.

Why do I need to run a function with if-statements multiple times to reach other statements?

void _checkbothloc(BuildContext context) {
if (_permissionGranted != PermissionStatus.GRANTED) {
_requestPermission();
} else if (_serviceEnabled != true) {
_requestService();
} else {
_takePicture(context);
}
}
Why do I have to run _checkbothloc 3 times to get to _takePicture(context)?
Does anyone have the same problem and have found a solution?
_takePicture is only reached the third time because you are using else / else if blocks. Instead, you would want to set up your function without them:
void _checkbothloc(BuildContext context) {
if (_permissionGranted != PermissionStatus.GRANTED) {
_requestPermission();
}
if (_serviceEnabled != true) {
_requestService();
}
_takePicture(context);
}
This way the conditions do not depend on each other and will both run no matter what. This also means that _takePicture will always be run, just sometimes the permission needs to be requested before and sometimes the service needs to be requested before.
Learn more about control flow statements in Dart.
You also need to ensure that _requestPermission and _requestService do not run asynchronously. If that is the case, mark your function as async and await these.
Learn more about asynchronous programming in Dart.

Flutter getting an exception when calling queryPastPurchases (in_app_purchase plugin): Cannot find receipt for the current main bundle

I'm trying to utilise the in_app_purchase plugin (https://pub.dev/packages/in_app_purchase) for my Flutter App.
Calling a queryProductDetails(ids) works just fine,
but when calling the queryPastPurchases() I get the following exception:
PlatformException (PlatformException(storekit_no_receipt, Cannot find receipt for the current main bundle., null))
Seems like this is the source for the exception:
https://github.com/flutter/plugins/blob/master/packages/in_app_purchase/ios/Classes/FIAPReceiptManager.m
Worth mentioning:
I've setup an IAP in App-Store-Connect.
This IAP hasn't been sent for Apple approval yet.
App is in development, tested using TestFlight with beta testers.
Another issue is that this exception doesn't get cought in the try-catch statement (see code below), but only by the environment when checking the "All Exceptions" option in VSCode...
Tested on Emulator and real device.
[UPDATE]:
Added a breakpoint to the objective-c code of the plugin, and saw that the receiptURL refers to "sandboxReceipt". So maybe it's because I don't use sandbox users?
Future<void> _getPastPurchases() async {
try {
final QueryPurchaseDetailsResponse response = await InAppPurchaseConnection.instance.queryPastPurchases();
if (response.error != null) {
// Handle the error
print(response.error.toString());
}
print('response = ' + response.toString());
for (PurchaseDetails purchase in response.pastPurchases) {
if (Platform.isIOS) {
//InAppPurchaseConnection.instance.completePurchase(purchase);
}
}
setState(() {
_purchases = response.pastPurchases;
});
} on PlatformException catch(err) {
print(err.toString());
}
catch (err) {
print(err.toString());
}
}