-
Notifications
You must be signed in to change notification settings - Fork 3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[pigeon]: Support of modern asynchronous api for Swift and Kotlin #8341
base: main
Are you sure you want to change the base?
Conversation
@@ -25,6 +25,16 @@ private class PigeonApiImplementation: ExampleHostApi { | |||
} | |||
completion(.success(true)) | |||
} | |||
|
|||
func sendMessageModernAsync(message: MessageData) async throws -> Bool { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you can just overload the function name func sendMessage(...)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think that I understood.
It's generated Host API code. We could not overload functions in Dart even if we do in Swift
@@ -25,6 +25,16 @@ private class PigeonApiImplementation: ExampleHostApi { | |||
} | |||
completion(.success(true)) | |||
} | |||
|
|||
func sendMessageModernAsync(message: MessageData) async throws -> Bool { | |||
try? await Task.sleep(nanoseconds: 2_000_000_000) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is this used for unit test? we shouldn't wait for so long as it slows down the tests
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is used in example app for demonstration purposes
I am not sure if it is used in any tests. I could remove this code if it is necessary
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Removed Task.sleep
Task { | ||
do { | ||
let result = try await api.sendMessageModernAsync(message: messageArg) | ||
DispatchQueue.main.async { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you can do Task { @MainActor }
here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you can do
Task { @MainActor }
here.
Do you mean:
sendMessageModernAsyncChannel.setMessageHandler { message, reply in
let args = message as! [Any?]
let messageArg = args[0] as! MessageData
Task {
do { @MainActor
let result = try await api.sendMessageModernAsync(message: messageArg)
reply(wrapResult(result))
} catch {
reply(wrapError(error))
}
}
}
Will it lead to executing api.sendMessageModernAsync
on main thread that could block it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, i meant you can replace DispatchQueue.main.async {}
with Task { @MainActor}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, i meant you can replace
DispatchQueue.main.async {}
withTask { @MainActor}
What's the point/profit?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The purpose of swift concurrency is to replace GCD. So since you are using swift concurrency here, there's no reason to use GCD at all.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
GCD
Okay I get it.
I am not very familiar with swift concurrency actually. Is that what you meant?
sendMessageModernAsyncChannel.setMessageHandler { message, reply in
let args = message as! [Any?]
let messageArg = args[0] as! MessageData
Task {
do {
let result = try await api.sendMessageModernAsync(message: messageArg)
await Task { @MainActor in
reply(wrapResult(result))
}
} catch {
await Task { @MainActor in
reply(wrapError(error))
}
}
}
}
Maybe we could use MainActor.run
instead? I think it is more readable.
sendMessageModernAsyncChannel.setMessageHandler { message, reply in
let args = message as! [Any?]
let messageArg = args[0] as! MessageData
Task {
do {
let result = try await api.sendMessageModernAsync(message: messageArg)
await MainActor.run(){
reply(wrapResult(result))
}
} catch {
await MainActor.run(){
reply(wrapError(error))
}
}
}
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In your first chunk of code, don't put await
in front of Task
.
For this particular case, you can use MainActor.run { ... }
, since reply
doesn't require an async context.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@hellohuanlin done
@@ -222,6 +223,30 @@ class ExampleHostApiSetup { | |||
} else { | |||
sendMessageChannel.setMessageHandler(nil) | |||
} | |||
let sendMessageModernAsyncChannel = FlutterBasicMessageChannel( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can we just reuse the channel?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can you point me to where this is used? im wondering if you can just use the original channel
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe i misunderstood how pigeon is used. Just a strawman - can we share the same channel for both old and new ways of doing things?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The way we use channels will not differ at all either "new way" or "old". We just can not use two handlers for one channel at the same time.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we have old api to be the wrapper of the new api?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you provide code sample of what you mean?
fdb7254
to
a8df692
Compare
a8df692
to
583d6d7
Compare
@hellohuanlin @LouiseHsu @tarrinneal CI check fails:
Do I need to bump version in |
@modernAsync
ModernAsync
annotation withSwiftModernAsynchronousOptions
to specify if method throwsResolves #123867, resolves #147283
Pre-launch Checklist
dart format
.)[shared_preferences]
pubspec.yaml
with an appropriate new version according to the pub versioning philosophy, or this PR is exempt from version changes.CHANGELOG.md
to add a description of the change, following repository CHANGELOG style, or this PR is exempt from CHANGELOG changes.///
).If you need help, consider asking for advice on the #hackers-new channel on Discord.