-
Notifications
You must be signed in to change notification settings - Fork 6k
New Plugin API PR4: Adds Lifecycle support to the new plugin system. #9049
New Plugin API PR4: Adds Lifecycle support to the new plugin system. #9049
Conversation
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
shell/platform/android/io/flutter/embedding/engine/FlutterEngineAndroidLifecycle.java
Outdated
Show resolved
Hide resolved
* {@code ContentProvider}, or {@code BroadcastReceiver}. In these cases, this lifecycle reports | ||
* itself in the {@link Lifecycle.State#CREATED} state. | ||
* <p> | ||
* Regardless of what happens to a backing {@code Activity} or @{code Service}, this lifecycle |
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.
It's unexpected to me that onDestroyed
would be special cased to the FlutterEngine
specifically and that it's impossible to get an onDestroyed
callback for the actual underlying lifecycle. Any way we could propagate this information life normal without breaking any kind of Engine contract? Add in an onEngineDestroyed
method just for this class to handle the final engine destruction?
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 contract that we're trying not to violate is the Lifecycle
contract, not the FlutterEngine
contract: https://developer.android.com/reference/android/arch/lifecycle/Lifecycle.State#destroyed
The unique thing about FlutterEngine
is that its backing Lifecycle
can change over time. It goes from Activity
to Service
to nothing to Activity
again. There is nothing preventing us from forwarding an Activity
's ON_DESTROY
event, but then any other code that is designed to understand Lifecycle
events will have undefined behavior when the FlutterEngine
's Lifecycle
turns right around and emits an ON_CREATED
event. Additionally, it is also conceptually incorrect to send that ON_DESTROY
event because even though the Activity
has been destroyed, the FlutterEngine
remains, and at the end of the day this Lifecycle
is truly owned by the FlutterEngine
, it just temporarily takes on the Lifecycle
of various Android components.
Does that make sense?
32cb12c
to
8312cd7
Compare
8312cd7
to
e0c044c
Compare
flutter/engine@8dc3a4c...4c4c0f8 git log 8dc3a4c..4c4c0f8 --no-merges --oneline 4c4c0f8 Add plugin shim to facilitate old plugins in new embedding (#33478). (flutter/engine#9120) e8c2b17 Added support for transparent FlutterActivitys (#32740). (flutter/engine#9115) 19c5029 Roll src/third_party/skia 29e013deb476..1013ecfb3421 (3 commits) (flutter/engine#9130) 45d39e1 Revert "Roll src/third_party/dart fee615c5a5..d5405d06f4 (21 commits) (#9127)" (flutter/engine#9135) 44f1b44 Revert "Use track-widget-creation transformer included in the sdk. (#9085)" (flutter/engine#9134) ae14c5a Roll src/third_party/dart fee615c5a5..d5405d06f4 (21 commits) (flutter/engine#9127) 3ea7ac8 Roll src/third_party/skia 633db4db7672..29e013deb476 (3 commits) (flutter/engine#9128) 8ad0e2f Roll src/third_party/skia 25b63f91b3b4..633db4db7672 (4 commits) (flutter/engine#9125) 37e6e0c Roll src/third_party/skia 8f88b2da05d5..25b63f91b3b4 (2 commits) (flutter/engine#9121) 37b367e Allow specifying both Dart and non-Dart fixtures in engine unit-tests. (flutter/engine#9113) 28f2c05 Roll src/third_party/skia 1f02e8488551..8f88b2da05d5 (3 commits) (flutter/engine#9116) 0932008 Remove outdated TODOs (flutter/engine#9114) c880ca2 Roll src/third_party/dart 50b0d85804..fee615c5a5 (4 commits) 6e51513 Removing unused imports (flutter/engine#9108) 9ee2697 Roll src/third_party/skia d04aaa3a841a..1f02e8488551 (8 commits) (flutter/engine#9109) fa2e2d9 Add checks to constructors and add missing constructor members (flutter/engine#9106) 7e1788a Fix unopt variants of profile and release builds. (flutter/engine#9107) 867120c Better help message. (flutter/engine#9097) e27c6e8 Forward custom IDE flags to GN. (flutter/engine#9023) 6b4ca8d Roll src/third_party/skia 176b214f91bc..d04aaa3a841a (7 commits) (flutter/engine#9105) a207318 Roll src/third_party/dart ec4d48e241..50b0d85804 (87 commits) 0a6aeb3 Roll src/third_party/skia 213aa46af167..176b214f91bc (2 commits) (flutter/engine#9100) f2e22aa Roll src/third_party/skia 7730d7cb8fb2..213aa46af167 (3 commits) (flutter/engine#9098) 557db42 Roll src/third_party/skia de7e074e8190..7730d7cb8fb2 (2 commits) (flutter/engine#9096) 64a4a0e Roll src/third_party/skia f06b6d5469a5..de7e074e8190 (1 commits) (flutter/engine#9094) fdee625 Roll src/third_party/skia 7e5a64f517e4..f06b6d5469a5 (2 commits) (flutter/engine#9093) daf47f0 Roll src/third_party/skia dc01a84ae098..7e5a64f517e4 (1 commits) (flutter/engine#9092) 41e10f0 Fix internal break since listing contents can return null (flutter/engine#9078) cf1b203 Roll src/third_party/skia f33c95cd6f55..dc01a84ae098 (3 commits) (flutter/engine#9091) 2404cdc Rename macOS FLEPlugin* to FlutterPlugin* (flutter/engine#9074) 509a43f Apply minor cleanups to Android embedding (flutter/engine#9088) 0a0f330 Removed outdated deprecation comments (flutter/engine#9087) a44cbbf Delete BSDiff sources (flutter/engine#9086) 0f1ff3b Correct typos, adopt US spellings (flutter/engine#9081) 651c904 Use track-widget-creation transformer included in the sdk. (flutter/engine#9085) cfa524f New Plugin API PR4: Adds Lifecycle support to the new plugin system. (flutter/engine#9049) 6b8ac18 Roll src/third_party/skia d9430297e74a..f33c95cd6f55 (5 commits) (flutter/engine#9082) 11408ef Update macOS podspec version requirement (flutter/engine#9077) 66c6ae4 Roll src/third_party/skia a4b837971c4b..d9430297e74a (30 commits) (flutter/engine#9080) 9151b37 Roll src/third_party/skia 9339a8a61af0..a4b837971c4b (34 commits) (flutter/engine#9076) ee6a9c4 Fix unchecked operation warnings in FlutterMain (flutter/engine#9073) 333042c Roll third_party/dart/tools/sdks to 2.3.0 (flutter/engine#9072) 01b8c07 Roll src/third_party/skia f77dbd04b926..9339a8a61af0 (12 commits) (flutter/engine#9065) 26b4fb5 Roll src/third_party/dart e3edfd36b2..ec4d48e241 (7 commits) 9d2d58a Add mouse button support to the macOS shell (flutter/engine#9054) ...
flutter/engine@8dc3a4c...4c4c0f8 git log 8dc3a4c..4c4c0f8 --no-merges --oneline 4c4c0f8 Add plugin shim to facilitate old plugins in new embedding (flutter#33478). (flutter/engine#9120) e8c2b17 Added support for transparent FlutterActivitys (flutter#32740). (flutter/engine#9115) 19c5029 Roll src/third_party/skia 29e013deb476..1013ecfb3421 (3 commits) (flutter/engine#9130) 45d39e1 Revert &flutter#34;Roll src/third_party/dart fee615c5a5..d5405d06f4 (21 commits) (flutter#9127)&flutter#34; (flutter/engine#9135) 44f1b44 Revert &flutter#34;Use track-widget-creation transformer included in the sdk. (flutter#9085)&flutter#34; (flutter/engine#9134) ae14c5a Roll src/third_party/dart fee615c5a5..d5405d06f4 (21 commits) (flutter/engine#9127) 3ea7ac8 Roll src/third_party/skia 633db4db7672..29e013deb476 (3 commits) (flutter/engine#9128) 8ad0e2f Roll src/third_party/skia 25b63f91b3b4..633db4db7672 (4 commits) (flutter/engine#9125) 37e6e0c Roll src/third_party/skia 8f88b2da05d5..25b63f91b3b4 (2 commits) (flutter/engine#9121) 37b367e Allow specifying both Dart and non-Dart fixtures in engine unit-tests. (flutter/engine#9113) 28f2c05 Roll src/third_party/skia 1f02e8488551..8f88b2da05d5 (3 commits) (flutter/engine#9116) 0932008 Remove outdated TODOs (flutter/engine#9114) c880ca2 Roll src/third_party/dart 50b0d85804..fee615c5a5 (4 commits) 6e51513 Removing unused imports (flutter/engine#9108) 9ee2697 Roll src/third_party/skia d04aaa3a841a..1f02e8488551 (8 commits) (flutter/engine#9109) fa2e2d9 Add checks to constructors and add missing constructor members (flutter/engine#9106) 7e1788a Fix unopt variants of profile and release builds. (flutter/engine#9107) 867120c Better help message. (flutter/engine#9097) e27c6e8 Forward custom IDE flags to GN. (flutter/engine#9023) 6b4ca8d Roll src/third_party/skia 176b214f91bc..d04aaa3a841a (7 commits) (flutter/engine#9105) a207318 Roll src/third_party/dart ec4d48e241..50b0d85804 (87 commits) 0a6aeb3 Roll src/third_party/skia 213aa46af167..176b214f91bc (2 commits) (flutter/engine#9100) f2e22aa Roll src/third_party/skia 7730d7cb8fb2..213aa46af167 (3 commits) (flutter/engine#9098) 557db42 Roll src/third_party/skia de7e074e8190..7730d7cb8fb2 (2 commits) (flutter/engine#9096) 64a4a0e Roll src/third_party/skia f06b6d5469a5..de7e074e8190 (1 commits) (flutter/engine#9094) fdee625 Roll src/third_party/skia 7e5a64f517e4..f06b6d5469a5 (2 commits) (flutter/engine#9093) daf47f0 Roll src/third_party/skia dc01a84ae098..7e5a64f517e4 (1 commits) (flutter/engine#9092) 41e10f0 Fix internal break since listing contents can return null (flutter/engine#9078) cf1b203 Roll src/third_party/skia f33c95cd6f55..dc01a84ae098 (3 commits) (flutter/engine#9091) 2404cdc Rename macOS FLEPlugin* to FlutterPlugin* (flutter/engine#9074) 509a43f Apply minor cleanups to Android embedding (flutter/engine#9088) 0a0f330 Removed outdated deprecation comments (flutter/engine#9087) a44cbbf Delete BSDiff sources (flutter/engine#9086) 0f1ff3b Correct typos, adopt US spellings (flutter/engine#9081) 651c904 Use track-widget-creation transformer included in the sdk. (flutter/engine#9085) cfa524f New Plugin API PR4: Adds Lifecycle support to the new plugin system. (flutter/engine#9049) 6b8ac18 Roll src/third_party/skia d9430297e74a..f33c95cd6f55 (5 commits) (flutter/engine#9082) 11408ef Update macOS podspec version requirement (flutter/engine#9077) 66c6ae4 Roll src/third_party/skia a4b837971c4b..d9430297e74a (30 commits) (flutter/engine#9080) 9151b37 Roll src/third_party/skia 9339a8a61af0..a4b837971c4b (34 commits) (flutter/engine#9076) ee6a9c4 Fix unchecked operation warnings in FlutterMain (flutter/engine#9073) 333042c Roll third_party/dart/tools/sdks to 2.3.0 (flutter/engine#9072) 01b8c07 Roll src/third_party/skia f77dbd04b926..9339a8a61af0 (12 commits) (flutter/engine#9065) 26b4fb5 Roll src/third_party/dart e3edfd36b2..ec4d48e241 (7 commits) 9d2d58a Add mouse button support to the macOS shell (flutter/engine#9054) ...
I'm trying to use this lifecycle for the GoogleMaps plugin, when the plugin is initialized it needs to know the current state of the activity, drive the backing Google Map to the state, and forward activity lifecycle events to the backing Google Map. I guess the way to do that with the current API is to make the plugin ActivityAware, and treat the "current" activity as "destroyed" if it's not attached and only if it is attached use the lifecycle from the plugin binding as the source of the activity lifecycle? What do you think about providing a lifecycle object for the current "attached" activity as part of the ActivityAware interface, and a lifecycle object for the current service as part of ServiceAware instead of providing a single lifecycle object that may be backed by different lifecycles depending on the attachment state? |
The idea behind providing a single Lifecycle is that it shouldn't matter which component backs it. My guess is that most cases don't care, so splitting out multiple Lifecycle objects for Activity vs Service vs App ends up creating more work for the common case. |
The concrete cases in I think it's worth providing an activity lifecycle object for ActivityAware plugins to keep the plugin code cleaner and less error prone, if it's indeed common to need the lifecycle of an "activity or a service" I guess we can provide both lifecycle objects. |
Unfortunately I don't have concrete alternative examples because we just don't cover enough interesting use-cases in 1P at this point. But I would say, would sensors ever care which lifecycle they're listening to? e.g., BLE? Or how about analytics? Or databases? I could be wrong in my analysis, and I'm happy to reconsider, but I figured that most plugins over time will be used for non-UI purposes, because Flutter brings most UI capabilities and plugins need to fill in the non-UI details. For non-UI cases, it seems unlikely that a plugin would care about whether we're dealing with a Service or an Activity. If we do want to give a difference lifecycle for ActivityAware, then I think we should bite the bullet and offer it for ActivityAware and ServiceAware and not offer one at all in the standard binding. However confusing it might appear now, it would be doubly confusing to have overlap between the Lifecycle in the standard binding and the Lifecycle in ActivityAware. So I think at this point the question is, how do we effectively determine if an API change is in our best interest? I understand that it looks good in the 2 or so cases we've seen, but how can we ensure we do our due diligence for the general case? And if it is, how does this change impact the plugin extension/migration effort? CC @mklim |
This makes sense to me too.
@matthew-carroll my understanding is that a driving reason behind migrating the 1P plugins now is that we want to test the v2 embedding API as soon as possible and make sure that it's covering all of the ecosystem's needs. Given a hypothetical argument for an API surface and actual concrete plugins needing it to expose a different service like we're seeing now, I think it makes more sense to change it to support the known real use cases.
This comes back to the versioning problem again. I think we probably want to hold off on migrating them for now and wait until the API change rolls into stable. |
@mklim if we wait for it go stable then our "concrete" use-cases remain nearly as hypothetical as the hypothetical use-cases. The most difficult issues tend to be the ones that seem to appear from nowhere when we attempt to actually write the code. Our attempt to migrate these plugins may have shown an API improvement, but I have a difficult time trusting that improvement until we literally see it solve the problem... |
@matthew-carroll I don't follow. In this case @amirh actively started writing out a PR now and identified a problem as he was working on a PR today, so I don't think the use case is hypothetical. I do see how it's frustrating to have such a long tail on when we can use the API from its development. Flutter plugins try to guarantee support for Flutter stable as our minimum baseline. If we write the plugin to depend on a new API surface it'll be a compile time breakage unless we wait that long for it to roll, at least for as long as the v2 embedding is bundled into the Flutter SDK. Theoretically we could reflect on the new surface to avoid it being a compile time breakage, but that wouldn't help verify that the API surface better suits our use case. If we could depend on the v2 embedding outside of the Flutter SDK we wouldn't be limited to the latest stable roll. |
The problem may be very real. But the solution is hypothetical until we apply it. There could be alternative solutions, right? And there could be weird Android race conditions that we won't see until we try it. This Lifecycle API surface seems to be the greatest cause for concern in the entire plugin surface. Just because we make an adjustment doesn't mean that we've shaken out all the issues. In fact, I think the fact that we want to make a significant change to it is a great reason to make sure we exercise the new solution thoroughly. |
I'd suggest we first determine, given the information we have right now, what we think the API should look like. After we've done that we can talk about timelines, migrations, and potential compromises. |
Sure. Happy to talk about the API. It seems like we're all pretty close on that expectation, though. We can solidify the proposal, but then all of my concerns point towards us exercising that API. |
To make sure I understand you correctly - you're theoretically support splitting into 2 lifecycle objects if we had no timeline considerations? |
Yes, I'm open to giving a Lifecycle to ActivityAware and ServiceAware, and removing it from FlutterPluginBinding, if the ecosystem team believes that is a better experience for the entire ecosystem. I am very concerned with making that change and not completely validating it before the next stable. I understand the rationale that we have to believe it will be OK, but this whole exercise is about direct validation. And I do believe in the importance of direct validation. |
What if we wrote a PR tentatively using the new interface as soon as it was available and tested it locally with master, but waited on merging it until it was in stable? It's not perfect but that would at least locally validate the API before waiting for an entire roll cycle. |
That's definitely a step in the right direction. There was previously a lot of discouragement about creating staging branches. But I don't have any problem with staging branches. |
New Plugin API PR4: Adds Lifecycle support to the new plugin system.
I still need to send in a real
Lifecycle
fromFlutterFragment
, but this PR creates the behavior within the new plugin system to respond toLifecycle
events.This PR adds 2 Android libs to the engine:
PluginRegistry
.Intended lifecycle behavior
When there is no backing lifecycle, e.g.,
Activity
orService
, theFlutterEngine
reports itself in theCREATED
state. When either anActivity
or aService
is attached to theFlutterEngine
, theFlutterEngine
defers to whatever the lifecycle of that component reports. The only caveat to this behavior is that even if the backingActivity
orService
is destroyed, theFlutterEngine
will not send a destruction event. This is because anyLifecycle
that emits a destruction event is obligated to never send any future events, which would be inappropriate in our case.