public class FlutterEngineGroup {
final List<FlutterEngine> activeEngines = new ArrayList<>();
/** Create a FlutterEngineGroup whose child engines will share resources. */
public FlutterEngineGroup(@NonNull Context context) {
this(context, null);
}
/**
* Create a FlutterEngineGroup whose child engines will share resources. Use {@code dartVmArgs} to
* pass flags to the Dart VM during initialization.
*/
public FlutterEngineGroup(@NonNull Context context, @Nullable String[] dartVmArgs) {
FlutterLoader loader = FlutterInjector.instance().flutterLoader();
if (!loader.initialized()) {
loader.startInitialization(context.getApplicationContext());
loader.ensureInitializationComplete(context, dartVmArgs);
}
}
}
public FlutterEngine createAndRunDefaultEngine(@NonNull Context context) {
return createAndRunEngine(context, null);
}
public FlutterEngine createAndRunEngine(
@NonNull Context context, @Nullable DartEntrypoint dartEntrypoint) {
FlutterEngine engine = null;
if (dartEntrypoint == null) {
dartEntrypoint = DartEntrypoint.createDefault();
}
if (activeEngines.size() == 0) {
engine = createEngine(context);
engine.getDartExecutor().executeDartEntrypoint(dartEntrypoint);
} else {
engine = activeEngines.get(0).spawn(context, dartEntrypoint);//基于已有的这个engine进行spawn
}
activeEngines.add(engine);
@VisibleForTesting
/* package */ FlutterEngine createEngine(Context context) {
return new FlutterEngine(context);
}
@NonNull
/*package*/ FlutterEngine spawn(
@NonNull Context context, @NonNull DartEntrypoint dartEntrypoint) {
if (!isAttachedToJni()) {
throw new IllegalStateException(
"Spawn can only be called on a fully constructed FlutterEngine");
}
FlutterJNI newFlutterJNI =
flutterJNI.spawn(
dartEntrypoint.dartEntrypointFunctionName, dartEntrypoint.dartEntrypointLibrary);
return new FlutterEngine(
context, // Context.
null, // FlutterLoader. A null value passed here causes the constructor to get it from the
// FlutterInjector.
newFlutterJNI); // FlutterJNI.
}
FlutterJNI.spawn
public FlutterJNI spawn(
@Nullable String entrypointFunctionName, @Nullable String pathToEntrypointFunction) {
ensureRunningOnMainThread();
ensureAttachedToNative();
FlutterJNI spawnedJNI =
nativeSpawn(nativeShellHolderId, entrypointFunctionName, pathToEntrypointFunction);
Preconditions.checkState(
spawnedJNI.nativeShellHolderId != null && spawnedJNI.nativeShellHolderId > 0,
"Failed to spawn new JNI connected shell from existing shell.");
return spawnedJNI;
}
shell/platform/android/platform_view_android_jni_impl.cc
static jobject SpawnJNI(JNIEnv* env,
jobject jcaller,
jlong shell_holder,
jstring jEntrypoint,
jstring jLibraryUrl) {
auto spawned_shell_holder =
ANDROID_SHELL_HOLDER->Spawn(jni_facade, entrypoint, libraryUrl);
std::unique_ptr<AndroidShellHolder> AndroidShellHolder::Spawn(
std::shared_ptr<PlatformViewAndroidJNI> jni_facade,
const std::string& entrypoint,
const std::string& libraryUrl) const {
std::unique_ptr<flutter::Shell> shell = shell_->Spawn(
std::move(config.value()), on_create_platform_view, on_create_rasterizer);
return std::unique_ptr<AndroidShellHolder>(
new AndroidShellHolder(GetSettings(), jni_facade, thread_host_,
std::move(shell), weak_platform_view));
}
std::unique_ptr<Shell> Shell::Spawn(
RunConfiguration run_configuration,
const CreateCallback<PlatformView>& on_create_platform_view,
const CreateCallback<Rasterizer>& on_create_rasterizer) const {
auto shell_maker = [&](bool is_gpu_disabled) {
std::unique_ptr<Shell> result(CreateWithSnapshot(//main1
PlatformData{}, task_runners_, GetSettings(), vm_,
vm_->GetVMData()->GetIsolateSnapshot(), on_create_platform_view,
on_create_rasterizer,
[engine = this->engine_.get()](
Engine::Delegate& delegate,
const PointerDataDispatcherMaker& dispatcher_maker, DartVM& vm,
fml::RefPtr<const DartSnapshot> isolate_snapshot,
TaskRunners task_runners, const PlatformData& platform_data,
Settings settings, std::unique_ptr<Animator> animator,
fml::WeakPtr<IOManager> io_manager,
fml::RefPtr<SkiaUnrefQueue> unref_queue,
fml::WeakPtr<SnapshotDelegate> snapshot_delegate,
std::shared_ptr<VolatilePathTracker> volatile_path_tracker) {
return engine->Spawn(/*delegate=*/delegate,//main2
/*dispatcher_maker=*/dispatcher_maker,
/*settings=*/settings,
/*animator=*/std::move(animator));
},
is_gpu_disabled));
return result;
};
std::unique_ptr<Shell> result;
GetIsGpuDisabledSyncSwitch()->Execute(
fml::SyncSwitch::Handlers()
.SetIfFalse([&] { result = shell_maker(false); })
.SetIfTrue([&] { result = shell_maker(true); }));
result->shared_resource_context_ = io_manager_->GetSharedResourceContext();
result->RunEngine(std::move(run_configuration));//main3
return result;
}
std::unique_ptr<Engine> Engine::Spawn(
Delegate& delegate,
const PointerDataDispatcherMaker& dispatcher_maker,
Settings settings,
std::unique_ptr<Animator> animator) const {
auto result = std::make_unique<Engine>(
/*delegate=*/delegate,
/*dispatcher_maker=*/dispatcher_maker,
/*image_decoder_task_runner=*/
runtime_controller_->GetDartVM()->GetConcurrentWorkerTaskRunner(),
/*task_runners=*/task_runners_,
/*settings=*/settings,
/*animator=*/std::move(animator),
/*io_manager=*/runtime_controller_->GetIOManager(),
/*font_collection=*/font_collection_,
/*runtime_controller=*/nullptr);
result->runtime_controller_ = runtime_controller_->Spawn(
*result, // runtime delegate
settings_.advisory_script_uri, // advisory script uri
settings_.advisory_script_entrypoint, // advisory script entrypoint
settings_.idle_notification_callback, // idle notification callback
settings_.isolate_create_callback, // isolate create callback
settings_.isolate_shutdown_callback, // isolate shutdown callback
settings_.persistent_isolate_data // persistent isolate data
);
return result;
}
std::unique_ptr<RuntimeController> RuntimeController::Spawn(
RuntimeDelegate& client,
std::string advisory_script_uri,
std::string advisory_script_entrypoint,
const std::function<void(int64_t)>& idle_notification_callback,
const fml::closure& isolate_create_callback,
const fml::closure& isolate_shutdown_callback,
std::shared_ptr<const fml::Mapping> persistent_isolate_data) const {
auto result = std::make_unique<RuntimeController>(
client, vm_, isolate_snapshot_, task_runners_, snapshot_delegate_,
hint_freed_delegate_, io_manager_, unref_queue_, image_decoder_,
advisory_script_uri, advisory_script_entrypoint,
idle_notification_callback, platform_data_, isolate_create_callback,
isolate_shutdown_callback, persistent_isolate_data,
volatile_path_tracker_);
result->spawning_isolate_ = root_isolate_;
return result;
}
void Shell::RunEngine(
RunConfiguration run_configuration,
const std::function<void(Engine::RunStatus)>& result_callback) {
fml::TaskRunner::RunNowOrPostTask(
task_runners_.GetUITaskRunner(),
fml::MakeCopyable(
[run_configuration = std::move(run_configuration),
weak_engine = weak_engine_, result]() mutable {
if (!weak_engine) {
FML_LOG(ERROR) << "Could not launch engine with configuration - no engine.";
result(Engine::RunStatus::Failure);
return;
}
auto run_result = weak_engine->Run(std::move(run_configuration));
if (run_result == flutter::Engine::RunStatus::Failure) {
FML_LOG(ERROR) << "Could not launch engine with configuration.";
}
result(run_result);
}));
}
Engine::RunStatus Engine::Run(RunConfiguration configuration) {
last_entry_point_ = configuration.GetEntrypoint();
last_entry_point_library_ = configuration.GetEntrypointLibrary();
UpdateAssetManager(configuration.GetAssetManager());
if (runtime_controller_->IsRootIsolateRunning()) {
return RunStatus::FailureAlreadyRunning;
}
if (!runtime_controller_->LaunchRootIsolate(//main
settings_, //
configuration.GetEntrypoint(), //
configuration.GetEntrypointLibrary(), //
configuration.TakeIsolateConfiguration()) //
) {
return RunStatus::Failure;
}
return Engine::RunStatus::Success;
}
bool RuntimeController::LaunchRootIsolate(
const Settings& settings,
std::optional<std::string> dart_entrypoint,
std::optional<std::string> dart_entrypoint_library,
std::unique_ptr<IsolateConfiguration> isolate_configuration) {
DartIsolate::CreateRunningRootIsolate(
settings, //
isolate_snapshot_, //
task_runners_, //
std::make_unique<PlatformConfiguration>(this), //
snapshot_delegate_, //
hint_freed_delegate_, //
io_manager_, //
unref_queue_, //
image_decoder_, //
advisory_script_uri_, //
advisory_script_entrypoint_, //
DartIsolate::Flags{}, //
isolate_create_callback_, //
isolate_shutdown_callback_, //
dart_entrypoint, //
dart_entrypoint_library, //
std::move(isolate_configuration), //
volatile_path_tracker_, //
spawning_isolate_.lock().get() //
)
std::weak_ptr<DartIsolate> DartIsolate::CreateRunningRootIsolate(
const Settings& settings,
fml::RefPtr<const DartSnapshot> isolate_snapshot,
TaskRunners task_runners,
std::unique_ptr<PlatformConfiguration> platform_configuration,
fml::WeakPtr<SnapshotDelegate> snapshot_delegate,
fml::WeakPtr<HintFreedDelegate> hint_freed_delegate,
fml::WeakPtr<IOManager> io_manager,
fml::RefPtr<SkiaUnrefQueue> skia_unref_queue,
fml::WeakPtr<ImageDecoder> image_decoder,
std::string advisory_script_uri,
std::string advisory_script_entrypoint,
Flags isolate_flags,
const fml::closure& isolate_create_callback,
const fml::closure& isolate_shutdown_callback,
std::optional<std::string> dart_entrypoint,
std::optional<std::string> dart_entrypoint_library,
std::unique_ptr<IsolateConfiguration> isolate_configration,
std::shared_ptr<VolatilePathTracker> volatile_path_tracker,
const DartIsolate* spawning_isolate) {
auto isolate = CreateRootIsolate(settings, //main1
isolate_snapshot, //
task_runners, //
std::move(platform_configuration), //
snapshot_delegate, //
hint_freed_delegate, //
io_manager, //
skia_unref_queue, //
image_decoder, //
advisory_script_uri, //
advisory_script_entrypoint, //
isolate_flags, //
isolate_create_callback, //
isolate_shutdown_callback, //
std::move(volatile_path_tracker), //
spawning_isolate //
)
.lock();
isolate->RunFromLibrary(dart_entrypoint_library, //main2
dart_entrypoint, //
settings.dart_entrypoint_args //
)