-
Notifications
You must be signed in to change notification settings - Fork 6k
Extracted PlatformViewsChannel from PlatformViewsController. #7847
Extracted PlatformViewsChannel from PlatformViewsController. #7847
Conversation
0b1fa09
to
48c5e9b
Compare
|
||
/** | ||
* System channel that sends 2-way communication between Flutter and Android to | ||
* display Android Views within Flutter. |
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 channel and the PlatformViewsController isn't displaying the views, it configures them, and passes input events.
Maybe replace "to display Android Views within Flutter" with "to facilitate embedding of Android Views within a Flutter application".
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.
done
* An attempt was made to use platform views on a version of Android that platform | ||
* views does not support. | ||
*/ | ||
public static class InvalidPlatformVersionException extends IllegalStateException {} |
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'd favor just throwing IllegalStateException directly with an error message, these specialized exception types are feeling a little too boiler plate-y to me. There's a more detailed explanation on why it's good to reuse IllegallStateException directly in Effective Java item 72. Sending you the internal best practices link that explains it offline.
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.
done
@@ -47,11 +43,51 @@ | |||
// The texture registry maintaining the textures into which the embedded views will be rendered. | |||
private TextureRegistry mTextureRegistry; | |||
|
|||
// The messenger used to communicate with the framework over the platform views channel. | |||
private BinaryMessenger mMessenger; | |||
// The system channel used to communicate with Flutter about platform views. |
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'd keep it saying: to communicate with "the framework", this code is also part of Flutter.
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.
done
|
||
private final HashMap<Integer, VirtualDisplayController> vdControllers; | ||
|
||
private final PlatformViewsChannel.PlatformViewsHandler channelHandler = new PlatformViewsChannel.PlatformViewsHandler() { |
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.
What's the benefit of having this anonymous class over making PlatformViewsController implement the interface?
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 distinction is based on the intended use. Implementing an interface is a public statement that the given instance can be used as the interface. In other words, a PlatformViewsController could be used by client code as a PlatformViewsHandler. But if another area of code used this class as a PlatformViewsHandler, that would very likely break this code. What we really want is for this PlatformViewsController to own both a PlatformViewsChannel, as well as a PlatformViewsHandler. These are internal implementation details of a PlatformViewsController, rather than a public behavior of PlatformViewsController. Therefore, the PlatformViewsHandler is kept private and internal.
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 see.
What do you think about keeping the actual method implementations in this anonymous class (e.g inlining PlatformViewsController#createPlatformView
here).
We're adding quite a lot of indirection layers here, I'm convinced that all of them are justified but this one(see my note to self in the PR comment).
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.
So the recommendation is to avoid re-declaring each method within the outer class and to simply do the behavior within the anonymous class?
If so, then I think that should be fine. I think the only reason I didn't do that was because I was trying to create a minimal diff against the existing code. I wasn't sure at the time if you were in the middle of evolving this class.
So if you confirm that this change is a good resolution then I'll take care of 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.
Yeah I support inlining the implementation if there isn't a good reason to keep the methods separate.
return; | ||
} | ||
|
||
switch (call.method) { |
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 method is pretty long which makes it hard for me to follow, lets keep split out the handling of the each different switch case to its own separate methods.
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.
done
@matthew-carroll did you have plans to address comments from @amirh or should we close this PR? |
@cbracken I plan to address them |
@matthew-carroll any progress on this? |
I'm gonna try to refresh this PR this weekend and hopefully have it reviewable by Monday. |
48c5e9b
to
d450c83
Compare
@amirh I believe I've addressed your comments. I had to force push an update so that I could get the latest from master, and also because the first 2 commits had the wrong author info for me. |
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.
Almost LGTM
I just want to be convinced that the separation between the implementations in PlatformViewController and in the anonymous implementation of PlatformViewsHandler worth it or merge these 2 layers(see my other comments)
|
||
private final HashMap<Integer, VirtualDisplayController> vdControllers; | ||
|
||
private final PlatformViewsChannel.PlatformViewsHandler channelHandler = new PlatformViewsChannel.PlatformViewsHandler() { |
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 see.
What do you think about keeping the actual method implementations in this anonymous class (e.g inlining PlatformViewsController#createPlatformView
here).
We're adding quite a lot of indirection layers here, I'm convinced that all of them are justified but this one(see my note to self in the PR comment).
Coming back to this PR 3 months later it's almost like taking a fresh look: I like the separation of parsing the method channel message from handling it, I think it makes the code easier to follow when the parsing is complex. I was a little about the amount of extra indirection layers and the boilerplate that comes with them, but have convinced myself it makes sense, so a note to future-self as for why we're adding all this boilerplate: If I want to add a new
The separation between 1<-->2 we want to avoid a huge |
… Java file, and updated licenses accordingly.
672aad4
to
6f0a4a4
Compare
@amirh I rebased to fix some conflicts and then I inlined the channel handler implementation as you suggested. Are we good to merge in at this point? |
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.
LGTM
flutter/engine@f9ce016...008090b git log f9ce016..008090b --no-merges --oneline 008090b Extracted PlatformViewsChannel from PlatformViewsController. (flutter/engine#7847) a4abfb2 Text inline widget LibTxt/dart:ui implementation (flutter/engine#8207) The AutoRoll server is located here: https://autoroll.skia.org/r/flutter-engine-flutter-autoroll Documentation for the AutoRoller is here: https://skia.googlesource.com/buildbot/+/master/autoroll/README.md If the roll is causing failures, please contact the current sheriff (cbracken@google.com), and stop the roller if necessary.
This regression was introduced in #7847. The PlatformViewsChannel method call handler was always setting the result to `notImplemented` even after handling a result, this resulted in a "Reply already submitted" exception being thrown. Note that the method channel code is swallowing this exception and logging an error, so we didn't crash instead we were logging an error(this is why the integration test didn't fail). Filed flutter/flutter#33863 to make sure tests fail when such exceptions are thrown. This PR also cleans up an unused `NoSuchPlatformViewException` that was introduced in #7847. flutter/flutter#33866
This regression was introduced in flutter#7847. The PlatformViewsChannel method call handler was always setting the result to `notImplemented` even after handling a result, this resulted in a "Reply already submitted" exception being thrown. Note that the method channel code is swallowing this exception and logging an error, so we didn't crash instead we were logging an error(this is why the integration test didn't fail). Filed flutter/flutter#33863 to make sure tests fail when such exceptions are thrown. This PR also cleans up an unused `NoSuchPlatformViewException` that was introduced in flutter#7847. flutter/flutter#33866
flutter/engine@f9ce016...008090b git log f9ce016..008090b --no-merges --oneline 008090b Extracted PlatformViewsChannel from PlatformViewsController. (flutter/engine#7847) a4abfb2 Text inline widget LibTxt/dart:ui implementation (flutter/engine#8207) The AutoRoll server is located here: https://autoroll.skia.org/r/flutter-engine-flutter-autoroll Documentation for the AutoRoller is here: https://skia.googlesource.com/buildbot/+/master/autoroll/README.md If the roll is causing failures, please contact the current sheriff (cbracken@google.com), and stop the roller if necessary.
This PR extracts all platform view system channel communication into
PlatformViewsChannel
.The relationship between
PlatformViewsController
andPlatformViewsChannel
is analogous to multiple other relationships including:TextInputPlugin
andTextInputChannel
,AndroidKeyProcessor
andKeyEventChannel
, andAccessibilityBridge
andAccessibilityChannel
.The idea behind these relationships is that the channels codify the Android/Flutter communication API, while the other associated class handles any state and handler behavior.
At a technical level, this PR handles communication issues with
Exception
s so that the inner workings of method channels are completely hidden from down stream consumers.