graph LR
FlutterView-->|对应|DartVM-->|对应|Engine
分别由FlutterRenderer控制渲染flutter UI到platform侧的FlutterView,由AndroidTouchProcessor控制platform侧的FlutterView的touchEvent到flutter
graph LR
FlutterView-->|attachToFlutterEngine|FlutterEngine
FlutterView-->|interaction events to|FlutterEngine
FlutterEngine-->|renderTo|FlutterView
FlutterEngine-->FlutterRenderer-->|notify|FlutterJNI
RenderSurface-->|nofity surface event|FlutterRenderer
FlutterView-->|contains|RenderSurface
FlutterEngine-->|contains|PlatformViewsController-->|contains|AndroidTouchProcessor-->|sendTouchEvent|Flutter
下述为flutter1.12版本时的源码研究,新版2.0设计上已经进行优化见上面的图解
1.12时在new FlutterView时进行Engine和DartVM的构造和初始化,而在2.0上功能分离到FlutterEngine这个java class中
/**
* Flutter implementation of {@link android.app.Application}, managing
* application-level global initializations.
*/
//FlutterApplication
@CallSuper
public void onCreate() {
super.onCreate();
FlutterMain.startInitialization(this);
}
/** FlutterMain
* Starts initialization of the native system.
* @param applicationContext The Android application context.
*/
public static void startInitialization(@NonNull Context applicationContext) {
if (isRunningInRobolectricTest) {
return;
}
FlutterLoader.getInstance().startInitialization(applicationContext);
}
/** Finds Flutter resources in an application APK and also loads Flutter's native library.*/
//FlutterLoader
/**
* Starts initialization of the native system.
* @param applicationContext The Android application context.
*/
public void startInitialization(@NonNull Context applicationContext) {
startInitialization(applicationContext, new Settings());
}
/**Starts initialization of the native system.
* <p>
* This loads the Flutter engine's native library to enable subsequent JNI calls.
This also starts locating and unpacking Dart resources packaged in the app's APK.
* <p>*/
public void startInitialization(@NonNull Context applicationContext, @NonNull Settings settings) {
if (Looper.myLooper() != Looper.getMainLooper()) {
throw new IllegalStateException("startInitialization must be called on the main thread");
}
initConfig(applicationContext);
initResources(applicationContext);
System.loadLibrary("flutter");//flutter so源码位于engine\shell\platform\android下的BUILD.gn配置
VsyncWaiter
.getInstance((WindowManager) applicationContext.getSystemService(Context.WINDOW_SERVICE))
.init();
long initTimeMillis = SystemClock.uptimeMillis() - initStartTimestampMillis;
FlutterJNI.nativeRecordStartTimestamp(initTimeMillis);
}
//engine/shell/platform/android/library_loader.cc
// This is called by the VM when the shared library is first loaded.
// flutter so的初始化
JNIEXPORT jint JNI_OnLoad(JavaVM* vm, void* reserved) {
// Initialize the Java VM.
//Android进程在由zygote fork过程中已创建了JavaVM,每一个进程对应一个JavaVM。在这里只是将当前进程的JavaVM实例保存在静态变量,再将当前线程和JavaVM建立关联,获取JNIEnv实例,每个线程对应一个JNIEnv实例
fml::jni::InitJavaVM(vm);
JNIEnv* env = fml::jni::AttachCurrentThread();
bool result = false;
//注册c和java层双向调用的函数信息
// Register FlutterMain.
result = flutter::FlutterMain::Register(env);
// Register PlatformView
result = flutter::PlatformViewAndroid::Register(env);
// Register VSyncWaiter.
result = flutter::VsyncWaiterAndroid::Register(env);
return JNI_VERSION_1_4;
}
//engine/shell/platform/android/flutter_main.cc
bool FlutterMain::Register(JNIEnv* env) {
static const JNINativeMethod methods[] = {
{
.name = "nativeInit",
.signature = "(Landroid/content/Context;[Ljava/lang/String;Ljava/"
"lang/String;Ljava/lang/String;Ljava/lang/String;)V",
.fnPtr = reinterpret_cast<void*>(&Init),
},
{
.name = "nativeRecordStartTimestamp",
.signature = "(J)V",
.fnPtr = reinterpret_cast<void*>(&RecordStartTimestamp),
},
};
jclass clazz = env->FindClass("io/flutter/embedding/engine/FlutterJNI");
return env->RegisterNatives(clazz, methods, fml::size(methods)) == 0;
}
//VsyncWaiter
private VsyncWaiter(@NonNull WindowManager windowManager) {
this.windowManager = windowManager;
}
private final FlutterJNI.AsyncWaitForVsyncDelegate asyncWaitForVsyncDelegate = new FlutterJNI.AsyncWaitForVsyncDelegate() {
@Override
public void asyncWaitForVsync(long cookie) {
Choreographer.getInstance().postFrameCallback(new Choreographer.FrameCallback() {
@Override
public void doFrame(long frameTimeNanos) {
float fps = windowManager.getDefaultDisplay().getRefreshRate();
long refreshPeriodNanos = (long) (1000000000.0 / fps);
FlutterJNI.nativeOnVsync(frameTimeNanos, frameTimeNanos + refreshPeriodNanos, cookie);
}
});
}
};
public void init() {
FlutterJNI.setAsyncWaitForVsyncDelegate(asyncWaitForVsyncDelegate);
// TODO(mattcarroll): look into moving FPS reporting to a plugin
float fps = windowManager.getDefaultDisplay().getRefreshRate();
FlutterJNI.setRefreshRateFPS(fps);
}
//FlutterJNI
public static void setAsyncWaitForVsyncDelegate(@Nullable AsyncWaitForVsyncDelegate delegate) {
asyncWaitForVsyncDelegate = delegate;
}
// Called by native.
private static void asyncWaitForVsync(final long cookie) {
if (asyncWaitForVsyncDelegate != null) {
asyncWaitForVsyncDelegate.asyncWaitForVsync(cookie);
} else {
throw new IllegalStateException("An AsyncWaitForVsyncDelegate must be registered with FlutterJNI before asyncWaitForVsync() is invoked.");
}
}
public static native void nativeOnVsync(long frameTimeNanos, long frameTargetTimeNanos, long cookie);
public static void setRefreshRateFPS(float refreshRateFPS) {
FlutterJNI.refreshRateFPS = refreshRateFPS;
}
public static native void nativeRecordStartTimestamp(long initTimeMillis);
FlutterActivity extends Activity implements FlutterView.Provider, PluginRegistry, ViewFactory {
private final FlutterActivityDelegate delegate = new FlutterActivityDelegate(this, this);
// These aliases ensure that the methods we forward to the delegate adhere
// to relevant interfaces versus just existing in FlutterActivityDelegate.
private final FlutterActivityEvents eventDelegate = delegate;
private final FlutterView.Provider viewProvider = delegate;
private final PluginRegistry pluginRegistry = delegate;
public FlutterActivity() {
this.eventDelegate = this.delegate;
this.viewProvider = this.delegate;
this.pluginRegistry = this.delegate;
}
/**
* Returns the Flutter view used by this activity; will be null before
* {@link #onCreate(Bundle)} is called.
*/
public FlutterView getFlutterView() { return this.viewProvider.getFlutterView();}
}
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.eventDelegate.onCreate(savedInstanceState);
}
public final class FlutterActivityDelegate
implements FlutterActivityEvents, FlutterView.Provider,PluginRegistry {
private FlutterView flutterView;
private final Activity activity;
public FlutterActivityDelegate(Activity activity, FlutterActivityDelegate.ViewFactory viewFactory) {
this.activity = (Activity)Preconditions.checkNotNull(activity);
this.viewFactory = (FlutterActivityDelegate.ViewFactory)Preconditions.checkNotNull(viewFactory);
}
public FlutterView getFlutterView() {
return this.flutterView;
}
// The implementation of PluginRegistry forwards to flutterView.
@Override
public boolean hasPlugin(String key) {
return flutterView.getPluginRegistry().hasPlugin(key);
}
@Override
public Registrar registrarFor(String pluginKey) {
return flutterView.getPluginRegistry().registrarFor(pluginKey);
}
}
public void onCreate(Bundle savedInstanceState) {
FlutterMain.ensureInitializationComplete(this.activity.getApplicationContext(), args);
this.flutterView = this.viewFactory.createFlutterView(this.activity);
if (this.flutterView == null) {
FlutterNativeView nativeView = this.viewFactory.createFlutterNativeView();
this.flutterView = new FlutterView(this.activity, (AttributeSet)null, nativeView);
this.flutterView.setLayoutParams(matchParent);
this.activity.setContentView(this.flutterView);
}
if (loadIntent(activity.getIntent())) {
return;
}
String appBundlePath = FlutterMain.findAppBundlePath();
if (appBundlePath != null) {
runBundle(appBundlePath);
}
/** FlutterMain
* Blocks until initialization of the native system has completed.
* <p>
* Calling this method multiple times has no effect.*/
public static void ensureInitializationComplete(@NonNull Context applicationContext, @Nullable String[] args) {
if (isRunningInRobolectricTest) {
return;
}
FlutterLoader.getInstance().ensureInitializationComplete(applicationContext, args);
}
/** FlutterLoader
* Blocks until initialization of the native system has completed.
*/
public void ensureInitializationComplete(@NonNull Context applicationContext, @Nullable String[] args) {
FlutterJNI.nativeInit(applicationContext, shellArgs.toArray(new String[0]),
kernelPath, appStoragePath, engineCachesPath);
public static native void nativeInit()
//FlutterView extends SurfaceView
public FlutterView(Context context, AttributeSet attrs, FlutterNativeView nativeView) {
if (nativeView == null) {
this.mNativeView = new FlutterNativeView(activity.getApplicationContext());//main
} else {
this.mNativeView = nativeView;
}
this.mNativeView.attachViewAndActivity(this, activity);
this.mSurfaceCallback = new Callback() {
public void surfaceCreated(SurfaceHolder holder) {
FlutterView.this.assertAttached();
FlutterView.this.mNativeView.getFlutterJNI().onSurfaceCreated(holder.getSurface());//main
}
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
FlutterView.this.assertAttached();
FlutterView.this.mNativeView.getFlutterJNI().onSurfaceChanged(width, height);
}
public void surfaceDestroyed(SurfaceHolder holder) {
FlutterView.this.assertAttached();
FlutterView.this.mNativeView.getFlutterJNI().onSurfaceDestroyed();
}
};
this.getHolder().addCallback(this.mSurfaceCallback);
this.navigationChannel = new NavigationChannel(this.dartExecutor);
this.keyEventChannel = new KeyEventChannel(this.dartExecutor);
this.lifecycleChannel = new LifecycleChannel(this.dartExecutor);
this.localizationChannel = new LocalizationChannel(this.dartExecutor);
this.platformChannel = new PlatformChannel(this.dartExecutor);
this.systemChannel = new SystemChannel(this.dartExecutor);
this.settingsChannel = new SettingsChannel(this.dartExecutor);
public FlutterNativeView(@NonNull Context context, boolean isBackgroundView) {
mContext = context;
mPluginRegistry = new FlutterPluginRegistry(this, context);
mFlutterJNI = new FlutterJNI();
mFlutterJNI.addIsDisplayingFlutterUiListener(flutterUiDisplayListener);
this.dartExecutor = new DartExecutor(mFlutterJNI, context.getAssets());
mFlutterJNI.addEngineLifecycleListener(new EngineLifecycleListenerImpl());
attach(this, isBackgroundView);
assertAttached();
}
private void attach(FlutterNativeView view, boolean isBackgroundView) {
mFlutterJNI.attachToNative(isBackgroundView);
dartExecutor.onAttachedToJNI();
}
/**
* Attaches this {@code FlutterJNI} instance to Flutter's native engine, which allows
* for communication between Android code and Flutter's platform agnostic engine.
* <p>
* This method must not be invoked if {@code FlutterJNI} is already attached to native.
*/
@UiThread
public void attachToNative(boolean isBackgroundView) {
ensureRunningOnMainThread();
ensureNotAttachedToNative();
nativePlatformViewId = nativeAttach(this, isBackgroundView);
}
private void ensureNotAttachedToNative() {
if (nativePlatformViewId != null) {
throw new RuntimeException("Cannot execute operation because FlutterJNI is attached to native.");
}}
}
private native long nativeAttach(@NonNull FlutterJNI flutterJNI, boolean isBackgroundView);
//engine/shell/platform/android/platform_view_android_jni.cc
bool RegisterApi(JNIEnv* env) {
static const JNINativeMethod flutter_jni_methods[] = {
// Start of methods from FlutterJNI
{
.name = "nativeAttach",
.signature = "(Lio/flutter/embedding/engine/FlutterJNI;Z)J",
.fnPtr = reinterpret_cast<void*>(&AttachJNI),
},
{
.name = "nativeRunBundleAndSnapshotFromLibrary",
.signature = "(JLjava/lang/String;Ljava/lang/String;"
"Ljava/lang/String;Landroid/content/res/AssetManager;)V",
.fnPtr = reinterpret_cast<void*>(&RunBundleAndSnapshotFromLibrary),
},
}
// Called By Java
static jlong AttachJNI(JNIEnv* env,
jclass clazz,
jobject flutterJNI,
jboolean is_background_view) {
fml::jni::JavaObjectWeakGlobalRef java_object(env, flutterJNI);
auto shell_holder = std::make_unique<AndroidShellHolder>(
FlutterMain::Get().GetSettings(), java_object, is_background_view);
if (shell_holder->IsValid()) {
return reinterpret_cast<jlong>(shell_holder.release());
} else {
return 0;
}
}
graph LR
subgraph MessageLoopAndroid是MessageLoopImpl子类
MessageLoopImpl
end
AndroidShellHolder-->|contains|ThreadHost-->|contains|platform_thread
ThreadHost-->|contains|ui_thread
ThreadHost-->|contains|raster_thread
ThreadHost-->|contains|io_tread
ThreadHost-->|contains|profiler_thread
ui_thread-->|contains|TaskRunner-->|contains|MessageLoopImpl
//engine/shell/platform/android/android_shell_holder
ThreadHost thread_host_;
fml::WeakPtr<PlatformViewAndroid> platform_view_;
std::unique_ptr<Shell> shell_;
AndroidShellHolder::AndroidShellHolder(
flutter::Settings settings,
fml::jni::JavaObjectWeakGlobalRef java_object,
bool is_background_view)
: settings_(std::move(settings)), java_object_(java_object) {
if (is_background_view) {
thread_host_ = {thread_label, ThreadHost::Type::UI};
} else {
thread_host_ = {thread_label, ThreadHost::Type::UI | ThreadHost::Type::GPU |
ThreadHost::Type::IO};//main
}
fml::WeakPtr<PlatformViewAndroid> weak_platform_view;
Shell::CreateCallback<PlatformView> on_create_platform_view = //main
[is_background_view, java_object, &weak_platform_view](Shell& shell) {
std::unique_ptr<PlatformViewAndroid> platform_view_android;
platform_view_android = std::make_unique<PlatformViewAndroid>(
shell, // delegate
shell.GetTaskRunners(), // task runners
java_object, // java object handle for JNI interop
shell.GetSettings()
.enable_software_rendering // use software rendering
);
weak_platform_view = platform_view_android->GetWeakPtr();
return platform_view_android;
};
Shell::CreateCallback<Rasterizer> on_create_rasterizer = [](Shell& shell) {//main
return std::make_unique<Rasterizer>(shell, shell.GetTaskRunners());
};
// The current thread will be used as the platform thread. Ensure that the
// message loop is initialized.
fml::MessageLoop::EnsureInitializedForCurrentThread();
fml::RefPtr<fml::TaskRunner> platform_runner =
fml::MessageLoop::GetCurrent().GetTaskRunner();
gpu_runner = thread_host_.gpu_thread->GetTaskRunner();
ui_runner = thread_host_.ui_thread->GetTaskRunner();
io_runner = thread_host_.io_thread->GetTaskRunner();
//main
flutter::TaskRunners task_runners(thread_label, // label
platform_runner, // platform
gpu_runner, // gpu
ui_runner, // ui
io_runner // io
);
//main
shell_ =
Shell::Create(task_runners, // task runners
GetDefaultWindowData(), // window data
settings_, // settings
on_create_platform_view, // platform view create callback
on_create_rasterizer // rasterizer create callback
);
platform_view_ = weak_platform_view;
class Shell final : public PlatformView::Delegate,
public Animator::Delegate,
public Engine::Delegate,
public Rasterizer::Delegate,
public ServiceProtocol::Handler {
template <class T> using CreateCallback = std::function<std::unique_ptr<T>(Shell&)>;
std::unique_ptr<Shell> Shell::Create(
TaskRunners task_runners,
const WindowData window_data,
Settings settings,
Shell::CreateCallback<PlatformView> on_create_platform_view,
Shell::CreateCallback<Rasterizer> on_create_rasterizer) {
PerformInitializationTasks(settings);
PersistentCache::SetCacheSkSL(settings.cache_sksl);
auto vm = DartVMRef::Create(settings);//main
FML_CHECK(vm) << "Must be able to initialize the VM.";
auto vm_data = vm->GetVMData();
//main
return Shell::Create(std::move(task_runners), //
std::move(window_data), //
std::move(settings), //
vm_data->GetIsolateSnapshot(), // isolate snapshot
on_create_platform_view, //
on_create_rasterizer, //
std::move(vm) //
);
dart_vm_lifecycle.cc
DartVMRef DartVMRef::Create(Settings settings,
fml::RefPtr<DartSnapshot> vm_snapshot,
fml::RefPtr<DartSnapshot> isolate_snapshot) {
std::scoped_lock lifecycle_lock(gVMMutex);
// If there is already a running VM in the process, grab a strong reference to it.
if (auto vm = gVM.lock()) {
FML_DLOG(WARNING) << "Attempted to create a VM in a process where one was "
"already running. Ignoring arguments for current VM "
"create call and reusing the old VM.";
// There was already a running VM in the process,
return DartVMRef{std::move(vm)};
}
......
// If there is no VM in the process. Initialize one, hold the weak reference
// and pass a strong reference to the caller.
auto isolate_name_server = std::make_shared<IsolateNameServer>();
auto vm = DartVM::Create(std::move(settings), //
std::move(vm_snapshot), //
std::move(isolate_snapshot), //
isolate_name_server //
);
gVMData = vm->GetVMData();
gVMServiceProtocol = vm->GetServiceProtocol();
gVMIsolateNameServer = isolate_name_server;
gVM = vm;
if (settings.leak_vm) {
gVMLeak = new std::shared_ptr<DartVM>(vm);
}
return DartVMRef{std::move(vm)};
std::unique_ptr<Shell> Shell::Create(
TaskRunners task_runners,
const WindowData window_data,
Settings settings,
fml::RefPtr<const DartSnapshot> isolate_snapshot,
const Shell::CreateCallback<PlatformView>& on_create_platform_view,
const Shell::CreateCallback<Rasterizer>& on_create_rasterizer,
DartVMRef vm) {
PerformInitializationTasks(settings);
PersistentCache::SetCacheSkSL(settings.cache_sksl);
fml::AutoResetWaitableEvent latch;
std::unique_ptr<Shell> shell;
fml::TaskRunner::RunNowOrPostTask(
task_runners.GetPlatformTaskRunner(),//main
fml::MakeCopyable([&latch, //
vm = std::move(vm), //
&shell, //
task_runners = std::move(task_runners), //
window_data, //
settings, //
isolate_snapshot = std::move(isolate_snapshot), //
on_create_platform_view, //
on_create_rasterizer //
]() mutable {
shell = CreateShellOnPlatformThread(std::move(vm),
std::move(task_runners), //
window_data, //
settings, //
std::move(isolate_snapshot), //
on_create_platform_view, //
on_create_rasterizer //
);
latch.Signal();
}));
latch.Wait();
return shell;
std::unique_ptr<Shell> Shell::CreateShellOnPlatformThread(
DartVMRef vm,
TaskRunners task_runners,
const WindowData window_data,
Settings settings,
fml::RefPtr<const DartSnapshot> isolate_snapshot,
const Shell::CreateCallback<PlatformView>& on_create_platform_view,
const Shell::CreateCallback<Rasterizer>& on_create_rasterizer) {
auto shell =
std::unique_ptr<Shell>(new Shell(std::move(vm), task_runners, settings));
// Create the rasterizer on the GPU thread.
......
// Create the platform view on the platform thread (this thread).
auto platform_view = on_create_platform_view(*shell.get());
// Ask the platform view for the vsync waiter. This will be used by the engine
// to create the animator.
auto vsync_waiter = platform_view->CreateVSyncWaiter();
// Create the IO manager on the IO thread. The IO manager must be initialized
// first because it has state that the other subsystems depend on. It must
// first be booted and the necessary references obtained to initialize the
// other subsystems.
......
// Create the engine on the UI thread.
std::promise<std::unique_ptr<Engine>> engine_promise;
auto engine_future = engine_promise.get_future();
fml::TaskRunner::RunNowOrPostTask(
shell->GetTaskRunners().GetUITaskRunner(),//main
fml::MakeCopyable([&engine_promise, //
shell = shell.get(), //
&dispatcher_maker, //
&window_data, //
isolate_snapshot = std::move(isolate_snapshot), //
vsync_waiter = std::move(vsync_waiter), //
&weak_io_manager_future, //
&snapshot_delegate_future, //
&unref_queue_future //
]() mutable {
TRACE_EVENT0("flutter", "ShellSetupUISubsystem");
const auto& task_runners = shell->GetTaskRunners();
// The animator is owned by the UI thread but it gets its vsync pulses
// from the platform.
auto animator = std::make_unique<Animator>(*shell, task_runners,
std::move(vsync_waiter));
engine_promise.set_value(std::make_unique<Engine>(//main
*shell, //
dispatcher_maker, //
*shell->GetDartVM(), //
std::move(isolate_snapshot), //
task_runners, //
window_data, //
shell->GetSettings(), //
std::move(animator), //
weak_io_manager_future.get(), //
unref_queue_future.get(), //
snapshot_delegate_future.get() //
));
}));
if (!shell->Setup(std::move(platform_view), //main
engine_future.get(), //
rasterizer_future.get(), //
io_manager_future.get()) //
) {
return nullptr;
}
return shell;
Engine::Engine(Delegate& delegate,
const PointerDataDispatcherMaker& dispatcher_maker,
DartVM& vm,
fml::RefPtr<const DartSnapshot> isolate_snapshot,
TaskRunners task_runners,
const WindowData window_data,
Settings settings,
std::unique_ptr<Animator> animator,
fml::WeakPtr<IOManager> io_manager,
fml::RefPtr<SkiaUnrefQueue> unref_queue,
fml::WeakPtr<SnapshotDelegate> snapshot_delegate)
: delegate_(delegate),
settings_(std::move(settings)),
animator_(std::move(animator)),
activity_running_(true),
have_surface_(false),
image_decoder_(task_runners,
vm.GetConcurrentWorkerTaskRunner(),
io_manager),
task_runners_(std::move(task_runners)),
weak_factory_(this) {
// Runtime controller is initialized here because it takes a reference to this
// object as its delegate. The delegate may be called in the constructor and
// we want to be fully initilazed by that point.
runtime_controller_ = std::make_unique<RuntimeController>(
......
pointer_data_dispatcher_ = dispatcher_maker(*this);
Shell::Shell(DartVMRef vm, TaskRunners task_runners, Settings settings) {
// Install service protocol handlers.
......
bool Shell::Setup(std::unique_ptr<PlatformView> platform_view,
std::unique_ptr<Engine> engine,
std::unique_ptr<Rasterizer> rasterizer,
std::unique_ptr<ShellIOManager> io_manager) {
......
}
……
private void runBundle(String appBundlePath) {
if (!flutterView.getFlutterNativeView().isApplicationRunning()) {
FlutterRunArguments args = new FlutterRunArguments();
args.bundlePath = appBundlePath;
args.entrypoint = "main";
flutterView.runFromBundle(args);//main
}
}
public void runFromBundle(FlutterRunArguments args) {
assertAttached();
preRun();
mNativeView.runFromBundle(args);//main
postRun();
}
public void runFromBundle(FlutterRunArguments args) {
mFlutterJNI.runBundleAndSnapshotFromLibrary(//main
args.bundlePath,
args.entrypoint,
args.libraryPath,
mContext.getResources().getAssets()
);
applicationIsRunning = true;
/** FlutterJNI
* Executes a Dart entrypoint.
* <p>
* This can only be done once per JNI attachment because a Dart isolate can only be
* entered once.
*/
@UiThread
public void runBundleAndSnapshotFromLibrary(
@NonNull String bundlePath,
@Nullable String entrypointFunctionName,
@Nullable String pathToEntrypointFunction,
@NonNull AssetManager assetManager
) {
ensureRunningOnMainThread();
ensureAttachedToNative();
nativeRunBundleAndSnapshotFromLibrary(
nativePlatformViewId,
bundlePath,
entrypointFunctionName,
pathToEntrypointFunction,
assetManager
);
}
//engine/shell/platform/android/platform_view_android_jni.cc
static void RunBundleAndSnapshotFromLibrary(JNIEnv* env,
jobject jcaller,
jlong shell_holder,
jstring jBundlePath,
jstring jEntrypoint,
jstring jLibraryUrl,
jobject jAssetManager) {
auto asset_manager = std::make_shared<flutter::AssetManager>();
......
RunConfiguration config(std::move(isolate_configuration),
std::move(asset_manager));
{
auto entrypoint = fml::jni::JavaStringToString(env, jEntrypoint);
auto libraryUrl = fml::jni::JavaStringToString(env, jLibraryUrl);
if ((entrypoint.size() > 0) && (libraryUrl.size() > 0)) {
config.SetEntrypointAndLibrary(std::move(entrypoint),
std::move(libraryUrl));
} else if (entrypoint.size() > 0) {
config.SetEntrypoint(std::move(entrypoint));
}
}
ANDROID_SHELL_HOLDER->Launch(std::move(config));//main
//engine/shell/platform/android/android_shell_holder
void AndroidShellHolder::Launch(RunConfiguration config) {
if (!IsValid()) {
return;
}
shell_->RunEngine(std::move(config));
}
void Shell::RunEngine(RunConfiguration run_configuration) {
RunEngine(std::move(run_configuration), nullptr);
}
void Shell::RunEngine(
RunConfiguration run_configuration,
const std::function<void(Engine::RunStatus)>& result_callback) {
......
fml::TaskRunner::RunNowOrPostTask(
task_runners_.GetUITaskRunner(),//main
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));//main
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) {
auto isolate_launch_status =
PrepareAndLaunchIsolate(std::move(configuration));
Engine::RunStatus Engine::PrepareAndLaunchIsolate(
RunConfiguration configuration) {
if (configuration.GetEntrypointLibrary().empty()) {
if (!isolate->Run(configuration.GetEntrypoint(),//main
settings_.dart_entrypoint_args)) {
FML_LOG(ERROR) << "Could not run the isolate.";
return RunStatus::Failure;
}
}
bool DartIsolate::Run(const std::string& entrypoint_name,
const std::vector<std::string>& args,
const fml::closure& on_run) {
auto user_entrypoint_function =
Dart_GetField(Dart_RootLibrary(), tonic::ToDart(entrypoint_name.c_str()));
auto entrypoint_args = tonic::ToDart(args);
if (!InvokeMainEntrypoint(user_entrypoint_function, entrypoint_args)) {//main
return false;
}
static bool InvokeMainEntrypoint(Dart_Handle user_entrypoint_function,
Dart_Handle args) {
Dart_Handle start_main_isolate_function =
tonic::DartInvokeField(Dart_LookupLibrary(tonic::ToDart("dart:isolate")),
"_getStartMainIsolateFunction", {});
if (tonic::LogIfError(tonic::DartInvokeField(
Dart_LookupLibrary(tonic::ToDart("dart:ui")), "_runMainZoned",
{start_main_isolate_function, user_entrypoint_function, args}))) {//main
FML_LOG(ERROR) << "Could not invoke the main entrypoint.";
return false;
}
return true;
//hooks.dart
@pragma('vm:entry-point')
// ignore: unused_element
void _runMainZoned(Function startMainIsolateFunction,//main
Function userMainFunction,//main
List<String> args) {
startMainIsolateFunction((){
runZoned<void>(() {
if (userMainFunction is _BinaryFunction) {
// This seems to be undocumented but supported by the command line VM.
// Let's do the same in case old entry-points are ported to Flutter.
(userMainFunction as dynamic)(args, '');
} else if (userMainFunction is _UnaryFunction) {
(userMainFunction as dynamic)(args);
} else {
userMainFunction();
}
}, onError: (Object error, StackTrace stackTrace) {
_reportUnhandledException(error.toString(), stackTrace.toString());
});
}, null);
}