How can I explicitly resolve a future(or any other await-able type) in dart , just like javascript
Completer class : A way to produce Future objects and to complete them later with a value or error.
Related
Let's say, in Dart/Flutter you are designing a plugin API have a function like this:
static Future<void> startPlaying(Uint8List bytes) async {
_channel.invokeMethod('playBytes', bytes);
}
Would it be true to say that, thanks to the null-safety feature of Dart, we are not responsible in the event that the 'bytes' parameter is passed in as null by the plugin user (and thus causing a runtime crash) because in order to do so, they would have to explicitly unwrap a nullable variable, thereby promising that it is is not null.
OR... is there some other thing we should do such as throwing an exception?
With sound null safety, there is no way to call that method with null as argument.
With unsound null safety, which is what you get if not every library of your program is opted into null safety, it's technically possible to pass null as an argument (because a non-null safe library could be doing the calling, or could be passing null into other null safe code, which doesn't check because it assumes null safety.)
You can choose to check the value coming in, as an extra precaution.
The language makes that hard for you, because locally the code looks null safe.
Something like
if (bytes as dynamic == null) throw ArgumentError.notNull("bytes");
I personally wouldn't bother with that, unless there is a real risk of something going spectacularly wrong if null manages to get into the code.
It's documented as not allowing a null value, and most well-behaved code will respect that. Eventually, when all programs are soundly null safe, that check would just be dead code.
First:
if you mean the final user that use app on device, you should have a validation for input.
Second:
if you mean someone try your plugin to code the app.
you can add required keyword, the dart analysis give the user the error if don't pass bytes.
static Future<void> startPlaying({required Uint8List bytes}) async {
_channel.invokeMethod('playBytes', bytes);
}
I'm using an IO Library which returns a Future<String>. While, yes, the returned type is String instead of String?, the documentation of that library method clearly states that null will be returned if the operation fails (Instead of throwing an exception). Therefore, I need to check for null myself and handle the exception throwing myself.
However, if I check the return value for null, Dart tells me that the operand can't be null and I therefore shouldn't be checking for it.
What should be done in such a case?
As is discussed in the comments, this issue can be seen when using legacy code that hasn't been updated for Dart 2.12 with null-safety.
In previous versions of Dart (pre-2.12), types did not have to have a trailing ? symbol to signify that a value may be null. A Future<String>, for example, could easily complete with a value of null.
To avoid this, make sure all your dependencies are null-safe.
Is there a better way to do this?
Assignment(
dueAt: json['due_at'] == null ?
null :
DateTime.parse(json['due_at']).toLocal()
)
The attribute "dueAt" in Assignment class can be null and i need to parse the string of json['due_at'] to a DateTime, but json['due_at'] can be null too.
Is not really a problem right now but seems noisy and repetitive.
First and foremost, it looks like you're writing JSON serialization code by hand. Your life will be much easier and less bug-prone if you let a library do this instead. json_serializable is very simple and powerful and 100% worth looking into.
However, this pattern is still common outside of json code.
You could also consider writing an extension method for Object? that behaves like the Kotlin standard library's let function (https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/let.html)
You can then use Dart's ?. syntax to handle the rest of the logic:
// extension on T rather than Object? to maintain type information
extension Example<T> on T {
R let<R>(R Function(T) function) => function(this);
}
This just applies a given function to this, which isn't incredibly useful on it's own, but allows the use of ?.:
final DateTime? dueAt = json['due_at']?.let(DateTime.parse);
If json['due_at'] evaluates to null, the ?. operator short-circuits, and dueAt is set to null. Otherwise, it evaluates to DateTime.parse(json['due_at']).
Or, you could just use package:kt_dart which ports much of the Kotlin standard library to Dart
In this particular case you may want to use tryParse instead of parse. If dueAt is of type DateTime? you can simply call:
Assignment( dueAt: DateTime.tryParse(json['due_at'])?.toLocal() );
Be aware though that tryParse will return null for any invalid date string (be it null or an improperly formatted string). This may or may not be desired behavior depending on your intended use.
I've recently upgraded Dart (using v2.12.4) and trying to migrate an app I've made.
I'm now stuck at an issue that I can't seem to resolve.
Consider the following pseudo-code:
class Notifications {
Future<List<NotificationItem>> notificationItems;
fillNotificationList() async {
notificationItems = await httpService.getFromEndpoint();
}
}
The notificationItems currently errors with Non-nullable instance field 'notifications' must be initialized..
I've tried different solutions; adding late keyword makes the application throw a LateInitializationError exception and appending = [] gives a type error.
How can I successfully have a Future variable with the null safety features in recent versions of Dart?
It seems to be a nullable variable. Meaning there is a point in time in your program where this is clearly null. So declare it as such:
Future<List<NotificationItem>>? notificationItems;
The rest of your code seems a little weird to me. You named a future like I would name the actual result. You have an async method that doesn't do any async work. Maybe that's just because the example here is simplified.
Or maybe you really really want to insist this is never null. You could initialize it with a completed Future with an empty list:
Future<List<NotificationItem>>? notificationItems = Future.value(<NotificationItem>[]);
The following gives a runtime error on the last line but why do I not receive a compile time error?
Why is this? fnSub (last line) accepts a type of Sub but here I'm passing it a type of Parent and it compiles. Ok, I do get a runtime error but I'd have thought this should have given me a compile time error. Is this a bug in Dart or am I misunderstanding the limitations of the type system or have I just gone crazy?
class Parent {}
class Sub implements Parent {
String get blah => "blah";
}
String fnSub(Sub sub) => sub.blah;
String aProblem(Parent parent) => fnSub(parent);
https://dartpad.dev/acd2767cd42371deae0644fa66e8c602
The problem is that implicit-casts are enabled by default in Dart which is a feature trying to make it easier to work around types in Dart by automatically adding type casts in your code base.
This feature will no longer be available when NNBD (Non-nullable by default) are coming where implicit-dynamic also will be gone. Both features can already be disabled today by following this guide: https://dart.dev/guides/language/analysis-options#enabling-additional-type-checks
Personally, I think most projects should disable this two features already since I have seen a lot of people on Stackoverflow being confused about what Dart are doing with the types. So I cannot wait for NNBD so we can get are lot more clear type experience in Dart. And hopefully, the errors from the analyzer will be clear enough for most people so they don't need to get help.
If you disable implicit-casts you code will fail at the following line:
String aProblem(Parent parent) => fnSub(parent);
And with this error:
error - The argument type 'Parent' can't be assigned to the parameter type 'Sub'. - bin\stackoverflow.dart:9:41 - argument_type_not_assignable
If you want to test with Dartpad you can try with the following edition based on a beta version of the next Dart version which has enabled null-safety (and therefore have no implicit-casts): https://nullsafety.dartpad.dev/