Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 5 additions & 3 deletions ci/licenses_golden/licenses_flutter
Original file line number Diff line number Diff line change
Expand Up @@ -556,6 +556,7 @@ FILE: ../../../flutter/shell/platform/android/apk_asset_provider.cc
FILE: ../../../flutter/shell/platform/android/apk_asset_provider.h
FILE: ../../../flutter/shell/platform/android/flutter_main.cc
FILE: ../../../flutter/shell/platform/android/flutter_main.h
FILE: ../../../flutter/shell/platform/android/io/flutter/FlutterInjector.java
FILE: ../../../flutter/shell/platform/android/io/flutter/Log.java
FILE: ../../../flutter/shell/platform/android/io/flutter/app/FlutterActivity.java
FILE: ../../../flutter/shell/platform/android/io/flutter/app/FlutterActivityDelegate.java
Expand Down Expand Up @@ -588,6 +589,10 @@ FILE: ../../../flutter/shell/platform/android/io/flutter/embedding/engine/Flutte
FILE: ../../../flutter/shell/platform/android/io/flutter/embedding/engine/dart/DartExecutor.java
FILE: ../../../flutter/shell/platform/android/io/flutter/embedding/engine/dart/DartMessenger.java
FILE: ../../../flutter/shell/platform/android/io/flutter/embedding/engine/dart/PlatformMessageHandler.java
FILE: ../../../flutter/shell/platform/android/io/flutter/embedding/engine/loader/FlutterLoader.java
FILE: ../../../flutter/shell/platform/android/io/flutter/embedding/engine/loader/ResourceCleaner.java
FILE: ../../../flutter/shell/platform/android/io/flutter/embedding/engine/loader/ResourceExtractor.java
FILE: ../../../flutter/shell/platform/android/io/flutter/embedding/engine/loader/ResourcePaths.java
FILE: ../../../flutter/shell/platform/android/io/flutter/embedding/engine/plugins/FlutterPlugin.java
FILE: ../../../flutter/shell/platform/android/io/flutter/embedding/engine/plugins/PluginRegistry.java
FILE: ../../../flutter/shell/platform/android/io/flutter/embedding/engine/plugins/activity/ActivityAware.java
Expand Down Expand Up @@ -657,9 +662,6 @@ FILE: ../../../flutter/shell/platform/android/io/flutter/view/FlutterMain.java
FILE: ../../../flutter/shell/platform/android/io/flutter/view/FlutterNativeView.java
FILE: ../../../flutter/shell/platform/android/io/flutter/view/FlutterRunArguments.java
FILE: ../../../flutter/shell/platform/android/io/flutter/view/FlutterView.java
FILE: ../../../flutter/shell/platform/android/io/flutter/view/ResourceCleaner.java
FILE: ../../../flutter/shell/platform/android/io/flutter/view/ResourceExtractor.java
FILE: ../../../flutter/shell/platform/android/io/flutter/view/ResourcePaths.java
FILE: ../../../flutter/shell/platform/android/io/flutter/view/TextureRegistry.java
FILE: ../../../flutter/shell/platform/android/io/flutter/view/VsyncWaiter.java
FILE: ../../../flutter/shell/platform/android/library_loader.cc
Expand Down
9 changes: 6 additions & 3 deletions shell/platform/android/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,7 @@ action("flutter_shell_java") {
source_jar_path = embedding_source_jar_path

sources = [
"io/flutter/FlutterInjector.java",
"io/flutter/Log.java",
"io/flutter/app/FlutterActivity.java",
"io/flutter/app/FlutterActivityDelegate.java",
Expand Down Expand Up @@ -155,6 +156,10 @@ action("flutter_shell_java") {
"io/flutter/embedding/engine/dart/DartExecutor.java",
"io/flutter/embedding/engine/dart/DartMessenger.java",
"io/flutter/embedding/engine/dart/PlatformMessageHandler.java",
"io/flutter/embedding/engine/loader/FlutterLoader.java",
"io/flutter/embedding/engine/loader/ResourceCleaner.java",
"io/flutter/embedding/engine/loader/ResourceExtractor.java",
"io/flutter/embedding/engine/loader/ResourcePaths.java",
"io/flutter/embedding/engine/plugins/FlutterPlugin.java",
"io/flutter/embedding/engine/plugins/PluginRegistry.java",
"io/flutter/embedding/engine/plugins/activity/ActivityAware.java",
Expand Down Expand Up @@ -224,9 +229,6 @@ action("flutter_shell_java") {
"io/flutter/view/FlutterNativeView.java",
"io/flutter/view/FlutterRunArguments.java",
"io/flutter/view/FlutterView.java",
"io/flutter/view/ResourceCleaner.java",
"io/flutter/view/ResourceExtractor.java",
"io/flutter/view/ResourcePaths.java",
"io/flutter/view/TextureRegistry.java",
"io/flutter/view/VsyncWaiter.java",
]
Expand Down Expand Up @@ -408,6 +410,7 @@ action("robolectric_tests") {
jar_path = "$root_out_dir/robolectric_tests.jar"

sources = [
"test/io/flutter/FlutterInjectorTest.java",
"test/io/flutter/FlutterTestSuite.java",
"test/io/flutter/SmokeTest.java",
"test/io/flutter/embedding/android/FlutterActivityAndFragmentDelegateTest.java",
Expand Down
114 changes: 114 additions & 0 deletions shell/platform/android/io/flutter/FlutterInjector.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

package io.flutter;

import android.support.annotation.NonNull;
import android.support.annotation.VisibleForTesting;

import io.flutter.embedding.engine.loader.FlutterLoader;

import java.lang.IllegalStateException;

/*
* This class is a simple dependency injector for the Android part of the Flutter engine.
*
* This simple solution is used facilitate testability without bringing in heavier app-development
* centric dependency injection frameworks such as Guice or Dagger2.
*/
public final class FlutterInjector {

private static FlutterInjector instance;
private static boolean accessed;

/*
* Use {@link FlutterInjector.Builder} to specify members to be injected via the static
* {@code FlutterInjector}.
*
* This can only be called at the beginning of the program before the {@link #instance()} is
* accessed.
*/
public static void setInstance(@NonNull FlutterInjector injector) {
if (accessed) {
throw new IllegalStateException("Cannot change the FlutterInjector instance once it's been " +
"read. If you're trying to dependency inject, be sure to do so at the beginning of " +
"the program");
}
instance = injector;
}

/*
* Retrieve the static instance of the {@code FlutterInjector} to use in your program.
*
* Once you access it, you can no longer change the values injected.
*
* If no override is provided for the injector, reasonable defaults are provided.
*/
public static FlutterInjector instance() {
accessed = true;
if (instance == null) {
instance = new Builder().build();
}
return instance;
}

// This whole class is here to enable testing so to test the thing that lets you test, some degree
// of hack is needed.
@VisibleForTesting
/* Package default */ static void reset() {
accessed = false;
instance = null;
}

private FlutterInjector(
boolean isRunningInRobolectricTest,
@NonNull FlutterLoader flutterLoader
) {
this.isRunningInRobolectricTest = isRunningInRobolectricTest;
this.flutterLoader = flutterLoader;
}

private boolean isRunningInRobolectricTest;
private FlutterLoader flutterLoader;

public boolean isRunningInRobolectricTest() {
return isRunningInRobolectricTest;
}

@NonNull
public FlutterLoader flutterLoader() {
return flutterLoader;
}

/*
* Builder used to supply a custom FlutterInjector instance to
* {@link FlutterInjector#setInstance(FlutterInjector)}.
*
* Non-overriden values have reasonable defaults.
*/
public static final class Builder {

private boolean isRunningInRobolectricTest = false;
public Builder setIsRunningInRobolectricTest(boolean isRunningInRobolectricTest) {
this.isRunningInRobolectricTest = isRunningInRobolectricTest;
return this;
}

private FlutterLoader flutterLoader;
public Builder setFlutterLoader(@NonNull FlutterLoader flutterLoader) {
this.flutterLoader = flutterLoader;
return this;
}

public FlutterInjector build() {
if (flutterLoader == null) {
flutterLoader = new FlutterLoader();
}

return new FlutterInjector(isRunningInRobolectricTest, flutterLoader);
}

}

}
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,10 @@
import java.util.HashSet;
import java.util.Set;

import io.flutter.FlutterInjector;
import io.flutter.Log;
import io.flutter.embedding.engine.dart.DartExecutor;
import io.flutter.embedding.engine.loader.FlutterLoader;
import io.flutter.embedding.engine.plugins.PluginRegistry;
import io.flutter.embedding.engine.plugins.activity.ActivityControlSurface;
import io.flutter.embedding.engine.plugins.broadcastreceiver.BroadcastReceiverControlSurface;
Expand All @@ -34,28 +36,38 @@

/**
* A single Flutter execution environment.
*
* WARNING: THIS CLASS IS EXPERIMENTAL. DO NOT SHIP A DEPENDENCY ON THIS CODE.
* IF YOU USE IT, WE WILL BREAK YOU.
*
* A {@code FlutterEngine} can execute in the background, or it can be rendered to the screen by
* using the accompanying {@link FlutterRenderer}. Rendering can be started and stopped, thus
* allowing a {@code FlutterEngine} to move from UI interaction to data-only processing and then
* back to UI interaction.
*
* <p>
* WARNING: THIS CLASS IS CURRENTLY EXPERIMENTAL. USE AT YOUR OWN RISK.
* <p>
* The {@code FlutterEngine} is the container through which Dart code can be run in an Android
* application.
* <p>
* Dart code in a {@code FlutterEngine} can execute in the background, or it can be render to the
* screen by using the accompanying {@link FlutterRenderer} and Dart code using the Flutter
* framework on the Dart side. Rendering can be started and stopped, thus allowing a
* {@code FlutterEngine} to move from UI interaction to data-only processing and then back to UI
* interaction.
* <p>
* Multiple {@code FlutterEngine}s may exist, execute Dart code, and render UIs within a single
* Android app.
*
* To start running Flutter within this {@code FlutterEngine}, get a reference to this engine's
* {@link DartExecutor} and then use {@link DartExecutor#executeDartEntrypoint(DartExecutor.DartEntrypoint)}.
* The {@link DartExecutor#executeDartEntrypoint(DartExecutor.DartEntrypoint)} method must not be
* <p>
* To start running Dart and/or Flutter within this {@code FlutterEngine}, get a reference to this
* engine's {@link DartExecutor} and then use
* {@link DartExecutor#executeDartEntrypoint(DartExecutor.DartEntrypoint)}. The
* {@link DartExecutor#executeDartEntrypoint(DartExecutor.DartEntrypoint)} method must not be
* invoked twice on the same {@code FlutterEngine}.
*
* <p>
* To start rendering Flutter content to the screen, use {@link #getRenderer()} to obtain a
* {@link FlutterRenderer} and then attach a {@link RenderSurface}. Consider using
* a {@link io.flutter.embedding.android.FlutterView} as a {@link RenderSurface}.
* {@link FlutterRenderer} and then attach a {@link RenderSurface}. Consider using a
* {@link io.flutter.embedding.android.FlutterView} as a {@link RenderSurface}.
* <p>
* Instatiating the first {@code FlutterEngine} per process will also load the Flutter engine's
* native library and start the Dart VM. Subsequent {@code FlutterEngine}s will run on the same VM
* instance but will have their own Dart <a
* href="https://api.dartlang.org/stable/dart-isolate/Isolate-class.html">Isolate</a> when the
* {@link DartExecutor} is run. Each Isolate is a self-contained Dart environment and cannot
* communicate with each other except via Isolate ports.
*/
// TODO(mattcarroll): re-evaluate system channel APIs - some are not well named or differentiated
public class FlutterEngine implements LifecycleOwner {
private static final String TAG = "FlutterEngine";

Expand Down Expand Up @@ -110,24 +122,31 @@ public void onPreEngineRestart() {

/**
* Constructs a new {@code FlutterEngine}.
*
* {@code FlutterMain.startInitialization} must be called before constructing a {@code FlutterEngine}
* to load the native libraries needed to attach to JNI.
*
* <p>
* A new {@code FlutterEngine} does not execute any Dart code automatically. See
* {@link #getDartExecutor()} and {@link DartExecutor#executeDartEntrypoint(DartExecutor.DartEntrypoint)}
* to begin executing Dart code within this {@code FlutterEngine}.
*
* <p>
* A new {@code FlutterEngine} will not display any UI until a
* {@link RenderSurface} is registered. See
* {@link #getRenderer()} and {@link FlutterRenderer#startRenderingToSurface(RenderSurface)}.
*
* <p>
* A new {@code FlutterEngine} does not come with any Flutter plugins attached. To attach plugins,
* see {@link #getPlugins()}.
*
* <p>
* A new {@code FlutterEngine} does come with all default system channels attached.
* <p>
* The first {@code FlutterEngine} instance constructed per process will also load the Flutter
* native library and start a Dart VM.
Copy link
Contributor

Choose a reason for hiding this comment

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

Can you describe the time and memory impact of this here?

Copy link
Member Author

Choose a reason for hiding this comment

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

Let's loop back to this after I write the website page for this this week-ish. I'd like to keep all these numbers in a centralized place that's easy to update if they change.

* <p>
* In order to pass Dart VM initialization arguments (see {@link io.flutter.embedding.engine.FlutterShellArgs})
* when creating the VM, manually set the initialization arguments by calling {@link FlutterMain#startInitialization(io.flutter.view.Context)}
* and {@link FlutterMain#ensureInitializationComplete(io.flutter.view.Context, String[])}.
*/
public FlutterEngine(@NonNull Context context) {
FlutterLoader flutterLoader = FlutterInjector.instance().flutterLoader();
flutterLoader.startInitialization(context);
FlutterLoader.ensureInitializationComplete(context, null);
this.flutterJNI = new FlutterJNI();
flutterJNI.addEngineLifecycleListener(engineLifecycleListener);
attachToJni();
Expand Down Expand Up @@ -174,9 +193,9 @@ private boolean isAttachedToJni() {
}

/**
* Cleans up all components within this {@code FlutterEngine} and then detaches from Flutter's
* native implementation.
*
* Cleans up all components within this {@code FlutterEngine} and destroys the associated Dart
* Isolate. All state held by the Dart Isolate, such as the Flutter Elements tree, is lost.
* <p>
* This {@code FlutterEngine} instance should be discarded after invoking this method.
*/
public void destroy() {
Expand Down Expand Up @@ -206,10 +225,10 @@ public void removeEngineLifecycleListener(@NonNull EngineLifecycleListener liste

/**
* The Dart execution context associated with this {@code FlutterEngine}.
*
* <p>
* The {@link DartExecutor} can be used to start executing Dart code from a given entrypoint.
* See {@link DartExecutor#executeDartEntrypoint(DartExecutor.DartEntrypoint)}.
*
* <p>
* Use the {@link DartExecutor} to connect any desired message channels and method channels
* to facilitate communication between Android and Dart/Flutter.
*/
Expand All @@ -220,7 +239,7 @@ public DartExecutor getDartExecutor() {

/**
* The rendering system associated with this {@code FlutterEngine}.
*
* <p>
* To render a Flutter UI that is produced by this {@code FlutterEngine}'s Dart code, attach
* a {@link RenderSurface} to this
* {@link FlutterRenderer}.
Expand Down
Loading