Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Conversation

@matthew-carroll
Copy link
Contributor

Android embedding refactor pr40 add static engine cache.

This PR includes testing dependency updates. Those updates have already been uploaded to CIPD and tagged, then re-synced locally to verify.

This PR changes the canonical way to use FlutterActivity and FlutterFragment to the following:

Create a default FlutterActivity:
Intent intent = FlutterActivity.createDefaultIntent();

Create a custom FlutterActivity with new FlutterEngine:
Intent intent = FlutterActivity.withNewEngine().dartEntrypoint("myEntry")...build();

Create a custom FlutterActivity with a cached FlutterEngine:
Intent intent = FlutterActivity.withCachedEngine("my_engine_id")...build();

Create a default FlutterFragment:
FlutterFragment fragment = FlutterFragment.createDefault();

Create a custom FlutterFragment with a new FlutterEngine:
FlutterFragment fragment = FlutterFragment.withNewEngine().dartEntrypoint("myEntry")...build();

Create a custom FlutterFragment with a cached FlutterEngine:
FlutterFragment fragment = FlutterFragment.withCachedEngine("my_engine_id")...build();

To cache a FlutterEngine:

FlutterEngine engine = new FlutterEngine(context);
// steps to begin executing Dart are omitted.
FlutterEngineCache.getInstance().put("my_engine_id", engine);

if (cachedEngineId != null) {
flutterEngine = FlutterEngineCache.getInstance().get(cachedEngineId);
isFlutterEngineFromHost = true;
if (flutterEngine == null) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is almost like an assert() to me. I do agree that we should validate that a cached engine exists but only in debug mode if it can be detected here. In release mode, perhaps we create an engine?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I considered that. The thing is, we'd be assuming the desired app bundle path, dart entrypoint, and initial route. Maybe we guess right, maybe not. If we get to this point and no cached engine exists, we have a fairly serious logic error. Now, if it's possible for this to happen due some kind of timing issue then we'd want to provide a better resolution, but if the dev simply forgot to put an engine in the cache then I don't think we can continue execution.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mehmetf @xster any further thoughts here? I'm open to alternatives if you think we should do something else. I just don't think we can assume a particular engine configuration to auto-create one.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we have to guess all of that then yes, I agree with you. We should fail.

* </ul>
* <p>
* {@code FlutterActivity} can be used with a cached {@link FlutterEngine} instead of creating a new
* one. Use {@link #withCachedEngine(String)} to build a {@code FlutterActivity} {@code Intent} that
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this be accompanied with some documentation change on when to use a cached engine?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there some existing documentation that you think should be updated?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not sure where the upstream user documentation for the new embedding is. Internally, it would be as part of the FAQ.

FlutterActivity can be used with a cached FlutterEngine.

but why and when should I use it with a cached Flutter Engine?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mehmetf @xster the only 2 times that I can think of that you wouldn't want to warm up an engine is:

  1. FlutterActivity is the first Activity that is launched, therefore rendering warm up redundant, or

  2. You have no idea when/if you'll need a Flutter experience and you don't want to waste the resources.

Can either of you think of other cases?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that's right. We can probably phrase the doc to say using a cached engine is generally recommended for optimal launch latency except where impossible such as in the cases listed.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated docs to reflect this.

Copy link
Member

@xster xster left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

awesome PR!!!
LGTM

* Creates an {@link IntentBuilder}, which can be used to configure an {@link Intent} to
* launch a {@code FlutterActivity}.
* Creates an {@link NewEngineIntentBuilder}, which can be used to configure an {@link Intent} to
* launch a {@code FlutterActivity} that internally creates a new {@link FlutterEngine} using
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for revisiting all these docs and clarifying.

* Creates a {@link CachedEngineIntentBuilder}, which can be used to configure an {@link Intent}
* to launch a {@code FlutterActivity} that internally uses an existing {@link FlutterEngine} that
* is cached in {@link FlutterEngineCache}.
*/
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we add a snippet showing how one caches a FlutterEngine in a FlutterEngineCache?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, done.

}

/**
* Returns true if the cached {@link FlutterEngine} should be destroyed and remoed from the
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

typo

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed.

@Override
@Nullable
public String getCachedEngineId() {
return getIntent().getStringExtra(EXTRA_CACHED_ENGINE_ID);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I forget how this works. If you made an activity with an Intent and rotate the screen, it's the same intent instance?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know about the Intent instance, but the Intent should report the same extras.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SG

*/
@Override
public boolean shouldDestroyEngineWithHost() {
return getIntent().getBooleanExtra(EXTRA_DESTROY_ENGINE_WITH_ACTIVITY, false);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Describe the default either in this doc or in the builder class or the builder factory.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done. I also updated FlutterActivity and FlutterFragment to set this value to true whenever the FlutterActivity/Fragment create its own FlutterEngine, or one is explicitly provided by subclassing. Do you think that's OK?

import java.util.Map;

/**
* Static singleton cache that holds {@link FlutterEngine} instances identified by {@code String}s.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Describe somewhere how that String relates to the engine instance. i.e. how do you get that string from an engine etc.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

* If a {@link FlutterEngine} already exists in this cache for the given {@code engineId}, that
* {@link FlutterEngine} is removed from this cache.
*/
public void put(@NonNull String engineId, @Nullable FlutterEngine engine) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oh it's full on whatever you make it? I guess that works too :)

// Create a spy around the FakeHost so that we can verify method invocations.
spyHost = spy(fakeHost);
// Create a mocked Host, which is required by the delegate being tested.
fakeHost = mock(FlutterActivityAndFragmentDelegate.Host.class);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

uber uber nit: you can call it mockHost at this point :D

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

}

@Test
public void itCreatesCachedEngineIntentThatDoesNotDestroyTheEngine() {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

awesome!

@matthew-carroll matthew-carroll merged commit 735255f into flutter:master Aug 6, 2019
engine-flutter-autoroll added a commit to engine-flutter-autoroll/flutter that referenced this pull request Aug 7, 2019
engine-flutter-autoroll added a commit to flutter/flutter that referenced this pull request Aug 7, 2019
git@github.com:flutter/engine.git/compare/42917704790d...9bfa4f5

git log 4291770..9bfa4f5 --no-merges --oneline
2019-08-07 stuartmorgan@google.com Roll buildroot back to an earlier version (flutter/engine#10681)
2019-08-07 stuartmorgan@google.com Roll buildroot to pick up EGL library name fix (flutter/engine#10679)
2019-08-06 chinmaygarde@google.com Remove semi-redundant try-jobs. (flutter/engine#10485)
2019-08-06 chinmaygarde@google.com Allow embedders to control Dart VM lifecycle on engine shutdown. (flutter/engine#10652)
2019-08-06 matthew-carroll@users.noreply.github.com Android embedding refactor pr40 add static engine cache (flutter/engine#10481)
2019-08-06 skia-flutter-autoroll@skia.org Roll fuchsia/sdk/core/linux-amd64 from W6ZtV... to 9sR9P... (flutter/engine#10672)
2019-08-06 bkonyi@google.com Roll src/third_party/dart 574c4a51c6..c262cbd414 (11 commits)
2019-08-06 stuartmorgan@google.com Roll buildroot for ANGLE support (flutter/engine#10667)

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 (jimgraham@google.com), and stop
the roller if necessary.
cyanglaz pushed a commit to cyanglaz/engine that referenced this pull request Aug 16, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants