flutter 是google推出的一套移动端高质量UI渲染框架,其引擎是自己的渲染引擎。
flutter 的UI渲染主要是两个线程在起作用:
UI线程:运行着UI Task Runner,是Flutter Engine用于执行Dart root isolate代码,将其转换为layer tree视图结构;处理页面元素的layout过程
Raster线程:该线程依然是在CPU上执行,处理layer tree并render子类对象,将其转换成为GPU命令并发送到GPU。
UI渲染概览
1.当需要渲染则会调用到Engine的ScheduleFrame()来注册VSYNC信号回调,一旦触发回调doFrame()执行完成后,便会移除回调方法,也就是说一次注册一次回调;
2.当需要再次绘制则需要重新调用到ScheduleFrame()方法,该方法的唯一重要参数regenerate_layer_tree决定在帧绘制过程是否需要重新生成layer tree,还是直接复用上一次的layer tree;
3.UI线程的绘制过程,最核心的是执行WidgetsBinding的drawFrame()方法,然后会创建layer tree视图树
再交由GPU Task Runner将layer tree提供的信息转化为平台可执行的GPU指令。
UI绘制核心工作
1)Vsync单注册模式:保证在一帧的时间窗口里UI线程只会生成一个layer tree发送给GPU线程,原理如下:
Animator中的信号量pending_frame_semaphore_用于控制不能连续频繁地调用Vsync请求,一次只能存在Vsync注册。 pending_frame_semaphore_初始值为1,在Animator::RequestFrame()消费信号会减1,当而后再次调用则会失败直接返回; Animator的BeginFrame()或者DrawLastLayerTree()方法会执行信号加1操作。
2)UI绘制最核心的方法是drawFrame(),包含以下几个过程:
Animate: 遍历transientCallbacks,执行动画回调方法;
Build: 对于dirty的元素会执行build构造,没有dirty元素则不会执行,对应于buildScope()
Layout: 计算渲染对象的大小和位置,对应于flushLayout(),这个过程可能会嵌套再调用build操作;
Compositing bits: 更新具有脏合成位的任何渲染对象, 对应于flushCompositingBits();
Paint: 将绘制命令记录到Layer, 对应于flushPaint();
Compositing: 将Compositing bits发送给GPU, 对应于compositeFrame();
Semantics: 编译渲染对象的语义,并将语义发送给操作系统, 对应于flushSemantics()。
UI线程的耗时从doFrame(frameTimeNanos)中的frameTimeNanos为起点,以小节Animator::Render()方法结束为终点, 并将结果保存到LayerTree的成员变量construction_time,这便是UI线程的耗时时长。
UI是如何渲染到UI上的:
1.首先我们知道flutter的运行开始点是:
void main() {
runApp(MyApp());
}
runApp需要传递的参数是widget,
void runApp(Widget app) {
//创建WidgetsFlutterBinding的单利
WidgetsFlutterBinding.ensureInitialized()
//将widget attach到root中
..scheduleAttachRootWidget(app)
//UI的渲染执行开始点
..scheduleWarmUpFrame();
}
下面是一系列的调用过程:
- 1.
scheduler/binding.dart #scheduleWarmUpFrame
void scheduleWarmUpFrame() {
...
Timer.run(() {
assert(_warmUpFrame);
handleDrawFrame();
resetEpoch();
_warmUpFrame = false;
if (hadScheduledFrame)
//继续调用
scheduleFrame();
});
...
}
- 2.
scheduler/binding.dart #scheduleFrame
void scheduleFrame() {
if (_hasScheduledFrame || !framesEnabled)
return;
assert(() {
if (debugPrintScheduleFrameStacks)
debugPrintStack(label: 'scheduleFrame() called. Current phase is $schedulerPhase.');
return true;
}());
ensureFrameCallbacksRegistered();
//这里调用的了window的scheduleFrame方法。window.dart中的方法都是对应于window.cc中的方法。
window.scheduleFrame();
_hasScheduledFrame = true;
}
- 3.
ui/widnow.dart #scheduleFrame
void scheduleFrame() native 'PlatformConfiguration_scheduleFrame';
window.cc
中RegisterNatives
注册了与window.dart
的关系
void Window::RegisterNatives(tonic::DartLibraryNatives* natives) {
natives->Register({
{"Window_defaultRouteName", DefaultRouteName, 1, true},
//这里window#scheduleFrame调用的是ScheduleFrame
{"Window_scheduleFrame", ScheduleFrame, 1, true},
{"Window_sendPlatformMessage", _SendPlatformMessage, 4, true},
{"Window_respondToPlatformMessage", _RespondToPlatformMessage, 3, true},
{"Window_render", Render, 2, true},
{"Window_updateSemantics", UpdateSemantics, 2, true},
{"Window_setIsolateDebugName", SetIsolateDebugName, 2, true},
{"Window_reportUnhandledException", ReportUnhandledException, 2, true},
{"Window_setNeedsReportTimings", SetNeedsReportTimings, 2, true},
{"Window_getPersistentIsolateData", GetPersistentIsolateData, 1, true},
{"Window_computePlatformResolvedLocale", _ComputePlatformResolvedLocale,
2, true},
});
}
2.到这里我们开始vsync的注册过程
- 1.window.cc中方法
void ScheduleFrame(Dart_NativeArguments args) {
UIDartState::ThrowIfUIOperationsProhibited();
UIDartState::Current()->window()->client()->ScheduleFrame();
}
- 2.runtime_controller.cc
void RuntimeController::ScheduleFrame() {
client_.ScheduleFrame();
}
这里的client_ 是engin.cc :由runtim_control_创建过程可知道
std::make_unique<RuntimeController>( *this...
- engin.cc
void Engine::ScheduleFrame(bool regenerate_layer_tree) {
animator_->RequestFrame(regenerate_layer_tree);
}
- 4.animator.cc
///头文件中 void ScheduleFrame(bool regenerate_layer_tree = true) override; 默认regenerate_layer_tree为true
///普通调用都是为true,特别的例子就是Shell::OnPlatformViewMarkTextureFrameAvailable()过程,设置参数为false,那么计划绘制一帧的时候就不需要重绘layer tree;
void Animator::RequestFrame(bool regenerate_layer_tree) {
//是否复用上一次的图层的标记量,默认true
if (regenerate_layer_tree) {
regenerate_layer_tree_ = true;
}
if (paused_ && !dimension_change_pending_) {
//暂停并且非挂起状态时也会被return
return;
}
//获取信号量,失败之后直接return,成功往下执行,防止注册两个vsync,
//flutter设计的原则当需要渲染则会调用到Engine的ScheduleFrame()来注册VSYNC信号回调,
//一旦触发回调doFrame()执行完成后,便会移除回调方法,
//也就是说一次注册一次回调,保证在一帧的时间窗口里UI线程只会生成一个layer tree发送给GPU线程
if (!pending_frame_semaphore_.TryWait()) {
return;
}
//将AwaitVSync post到UI线程执行
task_runners_.GetUITaskRunner()->PostTask([self = weak_factory_.GetWeakPtr(),
frame_number = frame_number_]() {
if (!self.get()) {
return;
}
TRACE_EVENT_ASYNC_BEGIN0("flutter", "Frame Request Pending", frame_number);
self->AwaitVSync();
});
frame_scheduled_ = true;
}
以上
pending_frame_semaphore_.TryWait
会尝试获取信号量,获取成功会执行,否则失败,在UI Thread中执行完AwaitVSync方法之后会将信号量释放。(以下方法DrawLastLayerTree
跟BeginFrame
中可见到)
- animator.cc
void Animator::AwaitVSync() {
waiter_->AsyncWaitForVsync(
[self = weak_factory_.GetWeakPtr()](fml::TimePoint frame_start_time,
fml::TimePoint frame_target_time) {
if (self) {
//是否可以复用上一次的LayerTree(图层)
if (self->CanReuseLastLayerTree()) {
self->DrawLastLayerTree();
} else {
self->BeginFrame(frame_start_time, frame_target_time);
}
}
});
delegate_.OnAnimatorNotifyIdle(dart_frame_deadline_);
}
///是否可以复用上一次的LayerTree(图层树)
bool Animator::CanReuseLastLayerTree() {
return !regenerate_layer_tree_;
}
regenerate_layer_tree_的值:
1.头文件中void ScheduleFrame(bool regenerate_layer_tree = true) override;
默认regenerate_layer_tree
为true
2.普通调用都是为true
3.特别的例子就是Shell::OnPlatformViewMarkTextureFrameAvailable()
过程,设置参数为false,那么计划绘制一帧的时候就不需要重绘layer tree;
waiter_ 的对值:
waiter_对应VsyncWaiter(vsync_waiter.cc)
,由构造方法时传入的参数,它是有平台属性的,android中对应于VsyncWaiterAndroid
,有也具有平台属性的PlatformViewAndroid(platform_view_android.cc)
#CreateVSyncWaiter
创建。(PlatformViewAndroid
继承自PlatformView
)
- 6.回调回来暂且不看,我们继续看VSYNC的注册过程
AsyncWaitForVsync
是调用在vsync_waiter.cc
中
void VsyncWaiter::AsyncWaitForVsync(const Callback& callback) {
if (!callback) {
return;
}
TRACE_EVENT0("flutter", "AsyncWaitForVsync");
{
std::scoped_lock lock(callback_mutex_);
if (callback_) {
//还是防止每一帧对应一个回调
TRACE_EVENT_INSTANT0("flutter", "MultipleCallsToVsyncInFrameInterval");
return;
}
//callback赋值
callback_ = std::move(callback);
if (secondary_callback_) {
// Return directly as `AwaitVSync` is already called by
// `ScheduleSecondaryCallback`.
return;
}
}
AwaitVSync();
}
1.6可知waiter_在android中是VsyncWaiterAndroid,所以AwaitVSync在android中执行的是VsyncWaiterAndroid下的AwaitVSync
- 7.
VsyncWaiterAndroid#AwaitVSync
(vsync_waiter_android.cc)
// |VsyncWaiter|
void VsyncWaiterAndroid::AwaitVSync() {
auto* weak_this = new std::weak_ptr<VsyncWaiter>(shared_from_this());
jlong java_baton = reinterpret_cast<jlong>(weak_this);
task_runners_.GetPlatformTaskRunner()->PostTask([java_baton]() {
JNIEnv* env = fml::jni::AttachCurrentThread();
env->CallStaticVoidMethod(g_vsync_waiter_class->obj(), //
g_async_wait_for_vsync_method_, //
java_baton //
);
});
}
其中
g_async_wait_for_vsync_method_
:asyncWaitForVsync
g_vsync_waiter_class
:env->FindClass("io/flutter/embedding/engine/FlutterJNI");
由此可见android中是进行了jni的调用,调用到了java层。
这两个值是在JNILoad的时候register的,会调用到VsyncWaiterAndroid::Register
。
- 8.
FlutterJNI#asyncWaitForVsync
(FlutterJNI.java)
// 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.");
}
}
- 9.VsyncWaiter.java
private final FlutterJNI.AsyncWaitForVsyncDelegate asyncWaitForVsyncDelegate =
new FlutterJNI.AsyncWaitForVsyncDelegate() {
@Override
public void asyncWaitForVsync(long cookie) {
//此处进行VSYNC的注册
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);
}
});
}
};
到了此刻便是我们熟悉的android framwork层了,VSYNC被注册并等待VSYNC的信号回调
doFrame
执行callback。有关于Choreographer
不做讲解,自行搜索文章。
初始化过程
上面1.7g_async_wait_for_vsync_method_
的初始化是在JNILoad的时候进行初始化的,具体过程为:
- 1.JNI_OnLoad (shell/platform/android/library_loader.cc)
// 首次加载共享库时此方法会被调用
JNIEXPORT jint JNI_OnLoad(JavaVM* vm, void* reserved) {
// 初始化java虚拟机
fml::jni::InitJavaVM(vm);
JNIEnv* env = fml::jni::AttachCurrentThread();
bool result = false;
// 注册FlutterMain
result = flutter::FlutterMain::Register(env);
FML_CHECK(result);
//注册PlatformViewAndroid
result = flutter::PlatformViewAndroid::Register(env);
FML_CHECK(result);
//注册VsyncWaiterAndroid
result = flutter::VsyncWaiterAndroid::Register(env);
FML_CHECK(result);
return JNI_VERSION_1_4;
}
- flutter_main.cc: 注册FlutterJNI的nativePrefetchDefaultFontManager以及nativeInit
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;J)V",
.fnPtr = reinterpret_cast<void*>(&Init),
},
{
.name = "nativePrefetchDefaultFontManager",
.signature = "()V",
.fnPtr = reinterpret_cast<void*>(&PrefetchDefaultFontManager),
},
};
jclass clazz = env->FindClass("io/flutter/embedding/engine/FlutterJNI");
if (clazz == nullptr) {
return false;
}
return env->RegisterNatives(clazz, methods, fml::size(methods)) == 0;
}
- 3.platform_view_android_jni_impl.cc #Register:此方法主要注册了
FlutterJNI,FlutterCallbackInformation,android/graphics/SurfaceTexture
等的类
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 = "nativeDestroy",
.signature = "(J)V",
.fnPtr = reinterpret_cast<void*>(&DestroyJNI),
},
{
.name = "nativeRunBundleAndSnapshotFromLibrary",
.signature = "(JLjava/lang/String;Ljava/lang/String;"
"Ljava/lang/String;Landroid/content/res/AssetManager;)V",
.fnPtr = reinterpret_cast<void*>(&RunBundleAndSnapshotFromLibrary),
},
{
.name = "nativeDispatchEmptyPlatformMessage",
.signature = "(JLjava/lang/String;I)V",
.fnPtr = reinterpret_cast<void*>(&DispatchEmptyPlatformMessage),
},
{
.name = "nativeDispatchPlatformMessage",
.signature = "(JLjava/lang/String;Ljava/nio/ByteBuffer;II)V",
.fnPtr = reinterpret_cast<void*>(&DispatchPlatformMessage),
},
{
.name = "nativeInvokePlatformMessageResponseCallback",
.signature = "(JILjava/nio/ByteBuffer;I)V",
.fnPtr =
reinterpret_cast<void*>(&InvokePlatformMessageResponseCallback),
},
{
.name = "nativeInvokePlatformMessageEmptyResponseCallback",
.signature = "(JI)V",
.fnPtr = reinterpret_cast<void*>(
&InvokePlatformMessageEmptyResponseCallback),
},
{
.name = "nativeNotifyLowMemoryWarning",
.signature = "(J)V",
.fnPtr = reinterpret_cast<void*>(&NotifyLowMemoryWarning),
},
// Start of methods from FlutterView
{
.name = "nativeGetBitmap",
.signature = "(J)Landroid/graphics/Bitmap;",
.fnPtr = reinterpret_cast<void*>(&GetBitmap),
},
{
.name = "nativeSurfaceCreated",
.signature = "(JLandroid/view/Surface;)V",
.fnPtr = reinterpret_cast<void*>(&SurfaceCreated),
},
{
.name = "nativeSurfaceWindowChanged",
.signature = "(JLandroid/view/Surface;)V",
.fnPtr = reinterpret_cast<void*>(&SurfaceWindowChanged),
},
{
.name = "nativeSurfaceChanged",
.signature = "(JII)V",
.fnPtr = reinterpret_cast<void*>(&SurfaceChanged),
},
{
.name = "nativeSurfaceDestroyed",
.signature = "(J)V",
.fnPtr = reinterpret_cast<void*>(&SurfaceDestroyed),
},
{
.name = "nativeSetViewportMetrics",
.signature = "(JFIIIIIIIIIIIIII)V",
.fnPtr = reinterpret_cast<void*>(&SetViewportMetrics),
},
{
.name = "nativeDispatchPointerDataPacket",
.signature = "(JLjava/nio/ByteBuffer;I)V",
.fnPtr = reinterpret_cast<void*>(&DispatchPointerDataPacket),
},
{
.name = "nativeDispatchSemanticsAction",
.signature = "(JIILjava/nio/ByteBuffer;I)V",
.fnPtr = reinterpret_cast<void*>(&DispatchSemanticsAction),
},
{
.name = "nativeSetSemanticsEnabled",
.signature = "(JZ)V",
.fnPtr = reinterpret_cast<void*>(&SetSemanticsEnabled),
},
{
.name = "nativeSetAccessibilityFeatures",
.signature = "(JI)V",
.fnPtr = reinterpret_cast<void*>(&SetAccessibilityFeatures),
},
{
.name = "nativeGetIsSoftwareRenderingEnabled",
.signature = "()Z",
.fnPtr = reinterpret_cast<void*>(&GetIsSoftwareRendering),
},
{
.name = "nativeRegisterTexture",
.signature = "(JJLandroid/graphics/SurfaceTexture;)V",
.fnPtr = reinterpret_cast<void*>(&RegisterTexture),
},
{
.name = "nativeMarkTextureFrameAvailable",
.signature = "(JJ)V",
.fnPtr = reinterpret_cast<void*>(&MarkTextureFrameAvailable),
},
{
.name = "nativeUnregisterTexture",
.signature = "(JJ)V",
.fnPtr = reinterpret_cast<void*>(&UnregisterTexture),
},
// Methods for Dart callback functionality.
{
.name = "nativeLookupCallbackInformation",
.signature = "(J)Lio/flutter/view/FlutterCallbackInformation;",
.fnPtr = reinterpret_cast<void*>(&LookupCallbackInformation),
},
// Start of methods for FlutterTextUtils
{
.name = "nativeFlutterTextUtilsIsEmoji",
.signature = "(I)Z",
.fnPtr = reinterpret_cast<void*>(&FlutterTextUtilsIsEmoji),
},
{
.name = "nativeFlutterTextUtilsIsEmojiModifier",
.signature = "(I)Z",
.fnPtr = reinterpret_cast<void*>(&FlutterTextUtilsIsEmojiModifier),
},
{
.name = "nativeFlutterTextUtilsIsEmojiModifierBase",
.signature = "(I)Z",
.fnPtr =
reinterpret_cast<void*>(&FlutterTextUtilsIsEmojiModifierBase),
},
{
.name = "nativeFlutterTextUtilsIsVariationSelector",
.signature = "(I)Z",
.fnPtr =
reinterpret_cast<void*>(&FlutterTextUtilsIsVariationSelector),
},
{
.name = "nativeFlutterTextUtilsIsRegionalIndicator",
.signature = "(I)Z",
.fnPtr =
reinterpret_cast<void*>(&FlutterTextUtilsIsRegionalIndicator),
},
};
if (env->RegisterNatives(g_flutter_jni_class->obj(), flutter_jni_methods,
fml::size(flutter_jni_methods)) != 0) {
FML_LOG(ERROR) << "Failed to RegisterNatives with FlutterJNI";
return false;
}
g_handle_platform_message_method =
env->GetMethodID(g_flutter_jni_class->obj(), "handlePlatformMessage",
"(Ljava/lang/String;[BI)V");
if (g_handle_platform_message_method == nullptr) {
FML_LOG(ERROR) << "Could not locate handlePlatformMessage method";
return false;
}
g_handle_platform_message_response_method = env->GetMethodID(
g_flutter_jni_class->obj(), "handlePlatformMessageResponse", "(I[B)V");
if (g_handle_platform_message_response_method == nullptr) {
FML_LOG(ERROR) << "Could not locate handlePlatformMessageResponse method";
return false;
}
g_update_semantics_method =
env->GetMethodID(g_flutter_jni_class->obj(), "updateSemantics",
"(Ljava/nio/ByteBuffer;[Ljava/lang/String;)V");
if (g_update_semantics_method == nullptr) {
FML_LOG(ERROR) << "Could not locate updateSemantics method";
return false;
}
g_update_custom_accessibility_actions_method = env->GetMethodID(
g_flutter_jni_class->obj(), "updateCustomAccessibilityActions",
"(Ljava/nio/ByteBuffer;[Ljava/lang/String;)V");
if (g_update_custom_accessibility_actions_method == nullptr) {
FML_LOG(ERROR)
<< "Could not locate updateCustomAccessibilityActions method";
return false;
}
g_on_first_frame_method =
env->GetMethodID(g_flutter_jni_class->obj(), "onFirstFrame", "()V");
if (g_on_first_frame_method == nullptr) {
FML_LOG(ERROR) << "Could not locate onFirstFrame method";
return false;
}
g_on_engine_restart_method =
env->GetMethodID(g_flutter_jni_class->obj(), "onPreEngineRestart", "()V");
if (g_on_engine_restart_method == nullptr) {
FML_LOG(ERROR) << "Could not locate onEngineRestart method";
return false;
}
g_create_overlay_surface_method =
env->GetMethodID(g_flutter_jni_class->obj(), "createOverlaySurface",
"()Lio/flutter/embedding/engine/FlutterOverlaySurface;");
if (g_create_overlay_surface_method == nullptr) {
FML_LOG(ERROR) << "Could not locate createOverlaySurface method";
return false;
}
g_destroy_overlay_surfaces_method = env->GetMethodID(
g_flutter_jni_class->obj(), "destroyOverlaySurfaces", "()V");
if (g_destroy_overlay_surfaces_method == nullptr) {
FML_LOG(ERROR) << "Could not locate destroyOverlaySurfaces method";
return false;
}
fml::jni::ScopedJavaLocalRef<jclass> overlay_surface_class(
env, env->FindClass("io/flutter/embedding/engine/FlutterOverlaySurface"));
if (overlay_surface_class.is_null()) {
FML_LOG(ERROR) << "Could not locate FlutterOverlaySurface class";
return false;
}
g_overlay_surface_id_method =
env->GetMethodID(overlay_surface_class.obj(), "getId", "()I");
if (g_overlay_surface_id_method == nullptr) {
FML_LOG(ERROR) << "Could not locate FlutterOverlaySurface#getId() method";
return false;
}
g_overlay_surface_surface_method = env->GetMethodID(
overlay_surface_class.obj(), "getSurface", "()Landroid/view/Surface;");
if (g_overlay_surface_surface_method == nullptr) {
FML_LOG(ERROR)
<< "Could not locate FlutterOverlaySurface#getSurface() method";
return false;
}
return true;
}
bool PlatformViewAndroid::Register(JNIEnv* env) {
if (env == nullptr) {
FML_LOG(ERROR) << "No JNIEnv provided";
return false;
}
g_flutter_callback_info_class = new fml::jni::ScopedJavaGlobalRef<jclass>(
env, env->FindClass("io/flutter/view/FlutterCallbackInformation"));
if (g_flutter_callback_info_class->is_null()) {
FML_LOG(ERROR) << "Could not locate FlutterCallbackInformation class";
return false;
}
g_flutter_callback_info_constructor = env->GetMethodID(
g_flutter_callback_info_class->obj(), "<init>",
"(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V");
if (g_flutter_callback_info_constructor == nullptr) {
FML_LOG(ERROR) << "Could not locate FlutterCallbackInformation constructor";
return false;
}
g_flutter_jni_class = new fml::jni::ScopedJavaGlobalRef<jclass>(
env, env->FindClass("io/flutter/embedding/engine/FlutterJNI"));
if (g_flutter_jni_class->is_null()) {
FML_LOG(ERROR) << "Failed to find FlutterJNI Class.";
return false;
}
g_mutators_stack_class = new fml::jni::ScopedJavaGlobalRef<jclass>(
env,
env->FindClass(
"io/flutter/embedding/engine/mutatorsstack/FlutterMutatorsStack"));
if (g_mutators_stack_class == nullptr) {
FML_LOG(ERROR) << "Could not locate FlutterMutatorsStack";
return false;
}
g_mutators_stack_init_method =
env->GetMethodID(g_mutators_stack_class->obj(), "<init>", "()V");
if (g_mutators_stack_init_method == nullptr) {
FML_LOG(ERROR) << "Could not locate FlutterMutatorsStack.init method";
return false;
}
g_mutators_stack_push_transform_method =
env->GetMethodID(g_mutators_stack_class->obj(), "pushTransform", "([F)V");
if (g_mutators_stack_push_transform_method == nullptr) {
FML_LOG(ERROR)
<< "Could not locate FlutterMutatorsStack.pushTransform method";
return false;
}
g_mutators_stack_push_cliprect_method = env->GetMethodID(
g_mutators_stack_class->obj(), "pushClipRect", "(IIII)V");
if (g_mutators_stack_push_cliprect_method == nullptr) {
FML_LOG(ERROR)
<< "Could not locate FlutterMutatorsStack.pushCilpRect method";
return false;
}
g_on_display_platform_view_method =
env->GetMethodID(g_flutter_jni_class->obj(), "onDisplayPlatformView",
"(IIIIIIILio/flutter/embedding/engine/mutatorsstack/"
"FlutterMutatorsStack;)V");
if (g_on_display_platform_view_method == nullptr) {
FML_LOG(ERROR) << "Could not locate onDisplayPlatformView method";
return false;
}
g_on_begin_frame_method =
env->GetMethodID(g_flutter_jni_class->obj(), "onBeginFrame", "()V");
if (g_on_begin_frame_method == nullptr) {
FML_LOG(ERROR) << "Could not locate onBeginFrame method";
return false;
}
g_on_end_frame_method =
env->GetMethodID(g_flutter_jni_class->obj(), "onEndFrame", "()V");
if (g_on_end_frame_method == nullptr) {
FML_LOG(ERROR) << "Could not locate onEndFrame method";
return false;
}
g_on_display_overlay_surface_method = env->GetMethodID(
g_flutter_jni_class->obj(), "onDisplayOverlaySurface", "(IIIII)V");
if (g_on_display_overlay_surface_method == nullptr) {
FML_LOG(ERROR) << "Could not locate onDisplayOverlaySurface method";
return false;
}
g_surface_texture_class = new fml::jni::ScopedJavaGlobalRef<jclass>(
env, env->FindClass("android/graphics/SurfaceTexture"));
if (g_surface_texture_class->is_null()) {
FML_LOG(ERROR) << "Could not locate SurfaceTexture class";
return false;
}
g_attach_to_gl_context_method = env->GetMethodID(
g_surface_texture_class->obj(), "attachToGLContext", "(I)V");
if (g_attach_to_gl_context_method == nullptr) {
FML_LOG(ERROR) << "Could not locate attachToGlContext method";
return false;
}
g_update_tex_image_method =
env->GetMethodID(g_surface_texture_class->obj(), "updateTexImage", "()V");
if (g_update_tex_image_method == nullptr) {
FML_LOG(ERROR) << "Could not locate updateTexImage method";
return false;
}
g_get_transform_matrix_method = env->GetMethodID(
g_surface_texture_class->obj(), "getTransformMatrix", "([F)V");
if (g_get_transform_matrix_method == nullptr) {
FML_LOG(ERROR) << "Could not locate getTransformMatrix method";
return false;
}
g_detach_from_gl_context_method = env->GetMethodID(
g_surface_texture_class->obj(), "detachFromGLContext", "()V");
if (g_detach_from_gl_context_method == nullptr) {
FML_LOG(ERROR) << "Could not locate detachFromGlContext method";
return false;
}
g_compute_platform_resolved_locale_method = env->GetMethodID(
g_flutter_jni_class->obj(), "computePlatformResolvedLocale",
"([Ljava/lang/String;)[Ljava/lang/String;");
if (g_compute_platform_resolved_locale_method == nullptr) {
FML_LOG(ERROR) << "Could not locate computePlatformResolvedLocale method";
return false;
}
return RegisterApi(env);
}
- 4.
VsyncWaiterAndroid#Register
(vsync_waiter_android.cc)
// static
bool VsyncWaiterAndroid::Register(JNIEnv* env) {
static const JNINativeMethod methods[] = {{
.name = "nativeOnVsync",
.signature = "(JJJ)V",
.fnPtr = reinterpret_cast<void*>(&OnNativeVsync),
}};
jclass clazz = env->FindClass("io/flutter/embedding/engine/FlutterJNI");
if (clazz == nullptr) {
return false;
}
g_vsync_waiter_class = new fml::jni::ScopedJavaGlobalRef<jclass>(env, clazz);
FML_CHECK(!g_vsync_waiter_class->is_null());
g_async_wait_for_vsync_method_ = env->GetStaticMethodID(
g_vsync_waiter_class->obj(), "asyncWaitForVsync", "(J)V");
FML_CHECK(g_async_wait_for_vsync_method_ != nullptr);
return env->RegisterNatives(clazz, methods, fml::size(methods)) == 0;
}
1.1.7中的方法调用,其中的
g_async_wait_for_vsync_method_
g_vsync_waiter_class
等字段此时被赋值
2.将FlutterJNI中的nativeOnVsync跟VsyncWaiterAndroid#OnNativeVsync进行绑定。