Äú¿ÉÒÔ¾èÖú£¬Ö§³ÖÎÒÃǵĹ«ÒæÊÂÒµ¡£

1Ôª 10Ôª 50Ôª





ÈÏÖ¤Â룺  ÑéÖ¤Âë,¿´²»Çå³þ?Çëµã»÷Ë¢ÐÂÑéÖ¤Âë ±ØÌî



  ÇóÖª ÎÄÕ ÎÄ¿â Lib ÊÓÆµ iPerson ¿Î³Ì ÈÏÖ¤ ×Éѯ ¹¤¾ß ½²×ù Model Center   Code  
»áÔ±   
   
 
     
   
 ¶©ÔÄ
  ¾èÖú
FlutteräÖȾ»úÖÆ¡ªUIÏß³Ì
 
×÷Õߣº²»Ïê
  2359  次浏览      27
2020-1-14
 
±à¼­ÍƼö:

±¾ÎÄÖ÷ÒªÏêϸ½éÉÜÁËUIÏß³ÌäÖȾ¡¢UIÏß³ÌäÖȾÁ÷³Ìͼ¡¢VSYNC×¢²áÁ÷³Ì£¬Framework²ã»æÖÆ£¬Ï£Íû¶ÔÄúÄÜÓÐËù°ïÖú¡£
±¾ÎÄÀ´×ÔÓÚgityuan,ÓÉ»ðÁú¹ûÈí¼þDelores±à¼­ÍƼö¡£

Ò»¡¢UIÏß³ÌäÖȾ

FlutterÊǹȸ迪ԴµÄÒÆ¶¯UI¿ò¼Ü£¬¿ÉÒÔ¿ìËÙÔÚAndroidºÍiOSÉϹ¹½¨³ö¸ßÖÊÁ¿µÄÔ­ÉúÓû§½çÃæ£¬Ä¿Ç°È«ÊÀ½çÔ½À´Ô½¶àµÄ¿ª·¢Õß¼ÓÈëµ½FlutterµÄ¶ÓÎé¡£ FlutterÏà±ÈRNÐÔÄܸüºÃ£¬ÓÉÓÚFlutter×Ô¼ºÊµÏÖÁËÒ»Ì×UI¿ò¼Ü£¬¶ªÆúÁËÔ­ÉúµÄUI¿ò¼Ü£¬·Ç³£½Ó½üÔ­ÉúµÄÌåÑé¡£

ΪÁ˽ÒÃØFlutter¸ßÐÔÄÜ£¬±¾ÎÄ´ÓÔ´Âë½Ç¶ÈÀ´¿´¿´FlutterµÄäÖȾ»æÖÆ»úÖÆ£¬¸úäÖȾֱ½ÓÏà¹ØµÄÁ½¸öÏß³ÌÊÇUIÏ̺߳ÍGPUỊ̈߳º

UIỊ̈߳ºÔËÐÐ×ÅUI Task Runner£¬ÊÇFlutter EngineÓÃÓÚÖ´ÐÐDart root isolate´úÂ룬½«Æäת»»Îªlayer treeÊÓͼ½á¹¹£»

GPUỊ̈߳º¸ÃÏß³ÌÒÀÈ»ÊÇÔÚCPUÉÏÖ´ÐУ¬ÔËÐÐ×ÅGPU Task Runner£¬´¦Àílayer tree£¬½«Æäת»»³ÉΪGPUÃüÁî²¢·¢Ë͵½GPU¡£

ͨ¹ýVSYNCÐźÅʹUIÏ̺߳ÍGPUÏß³ÌÓÐÌõ²»ÎɵÄÖÜÆÚÐÔµÄäÖȾ½çÃæ£¬±¾ÎĽéÉÜVSYNCµÄ²úÉú¹ý³Ì¡¢UIÏß³ÌÔÚÒýÇæºÍ¿ò¼ÜµÄ»æÖƹ¤×÷£¬ÏÂһƪÎÄÕ»á½éÉÜGPUÏ̵߳ĻæÖƹ¤×÷¡£

1.1 UIäÖȾԭÀí

1.1.1 UIäÖȾ¸ÅÀÀ

ͨ¹ýVSYNCÐźÅʹUIÏ̺߳ÍGPUÏß³ÌÓÐÌõ²»ÎɵÄÖÜÆÚÐÔµÄäÖȾ½çÃæ£¬ÈçÏÂͼËùʾ£º

µ±ÐèÒªäÖȾÔò»áµ÷Óõ½EngineµÄScheduleFrame()À´×¢²áVSYNCÐźŻص÷£¬Ò»µ©´¥·¢»Øµ÷doFrame()Ö´ÐÐÍê³Éºó£¬±ã»áÒÆ³ý»Øµ÷·½·¨£¬Ò²¾ÍÊÇ˵һ´Î×¢²áÒ»´Î»Øµ÷£»

µ±ÐèÒªÔٴλæÖÆÔòÐèÒªÖØÐµ÷Óõ½ScheduleFrame()·½·¨£¬¸Ã·½·¨µÄÎ¨Ò»ÖØÒª²ÎÊýregenerate_layer_tree¾ö¶¨ÔÚÖ¡»æÖƹý³ÌÊÇ·ñÐèÒªÖØÐÂÉú³Élayer tree£¬»¹ÊÇÖ±½Ó¸´ÓÃÉÏÒ»´ÎµÄlayer tree£»

UIÏ̵߳ĻæÖƹý³Ì£¬×îºËÐĵÄÊÇÖ´ÐÐWidgetsBindingµÄdrawFrame()·½·¨£¬È»ºó»á´´½¨layer treeÊÓͼÊ÷

ÔÙ½»ÓÉGPU Task Runner½«layer treeÌṩµÄÐÅϢת»¯ÎªÆ½Ì¨¿ÉÖ´ÐеÄGPUÖ¸Áî¡£

1.1.2 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ΪÆðµã£¬ÒÔС½Ú[4.10.6]Animator::Render()·½·¨½áÊøÎªÖյ㣬 ²¢½«½á¹û±£´æµ½LayerTreeµÄ³ÉÔ±±äÁ¿construction_time_£¬Õâ±ãÊÇUIÏ̵߳ĺÄʱʱ³¤¡£

1.1.3 Timeline˵Ã÷

3£©ÒÔÉϼ¸¸ö¹ý³ÌÔÚTimelineÖÐuiÏß³ÌÖж¼ÓÐÌåÏÖ£¬ÈçÏÂͼËùʾ£º

ÁíÍâTimelineÖл¹ÓÐÁ½¸ö±È½Ï³£¼ûµÄ±êÇ©Ïî

¡°Frame Request Pending¡±£º´ÓAnimator::RequestFrame µ½Animator::BeginFrame()½áÊø£»

¡±PipelineProduce¡°£º ´ÓAnimator::BeginFrame()µ½Animator::Render()½áÊø¡£

1.2 UIÏß³ÌäÖȾÁ÷³Ìͼ

1.2.1 VSYNC×¢²áÁ÷³Ì

VSYNC×¢²áÁ÷³Ìͼ

µ±µ÷Óõ½ÒýÇæEngineµÄScheduleFrame()·½·¨¹ý³ÌÔò»á×¢²áVSYNCÐźŻص÷£¬Ò»µ©VsyncÐźŴﵽ£¬Ôò»áµ÷Óõ½doFrame()·½·¨¡£ ¶ÔÓÚµ÷ÓÃScheduleFrame()µÄ³¡¾°ÓжàÖÖ£¬±ÈÈ綯»­µÄÖ´ÐÐAnimationController.forward()£¬ÔÙ±ÈÈç±ÈÈçsurface´´½¨µÄʱºòshell::SurfaceCreated()¡£

1.2.2 Engine²ã»æÖÆ

Engine²ã´¦ÀíÁ÷³Ìͼ

doFrame()¾­¹ý¶à²ãµ÷Óúóͨ¹ýPostTask½«ÈÎÎñÒì²½postµ½UI TaskRunnerÏß³ÌÀ´Ö´ÐУ¬×îºóµ÷Óõ½WindowµÄBeginFrame()·½·¨¡£

1.2.3 Framework²ã»æÖÆ

Framework²ã´¦ÀíÁ÷³Ìͼ

ÆäÖÐwindow.ccÖеÄÒ»¸öBeginFrame()·½·¨£¬»áµ÷Óõ½window.dartÖеÄonBeginFrame()ºÍonDrawFrame()Á½¸ö·½·¨¡£

1.3 ºËÐÄÀàͼ

Àà¹ØÏµÍ¼

ΪÁËÈôó¼Ò¸üÈÝÒ×Àí½âÔ´Â룬ÏÈ¿´Ò»ÕŹØÓÚShell¡¢Engine¡¢AnimatorµÈFlutterµÈFlutterÒýÇæÖкËÐÄÀàµÄÀàͼ¡£

WindowÀࣺÊÇÁ¬½ÓFlutter¿ò¼Ü²ã(Dart)ÓëÒýÇæ²ã(C++)µÄ¹Ø¼üÀ࣬ÔÚ¿ò¼Ü²ãÖÐwindow.dartÎļþÀïµÄһЩ·½·¨ÔÚÒýÇæ²ãµÄwindow.ccÎļþÓÐÏà¶ÔÓ¦µÄ·½·¨£¬±ÈÈçscheduleFrame()·½·¨¡£ ÔÚwindow.ccÀïÃæÍ¨¹ýWindow::RegisterNatives()×¢²áÁËһЩ¿ò¼Ü²ãÓëÒýÇæ²ãµÄ·½·¨¶ÔÓ¦¹ØÏµ£»

RuntimeControllerÀࣺ¿Éͨ¹ýÆä³ÉÔ±root_isolate_ÕÒµ½WindowÀࣻ

ShellÀࣺͬʱ¼Ì³ÐÁËPlatformView::Delegate£¬Animator::Delegate£¬Engine::Delegate£¬ËùÒÔÔÚEngine£¬Animator£¬PlatformViewÖеijÉÔ±±äÁ¿delegate_¶¼ÊÇÖ¸Shell¶ÔÏó£¬ ´ÓͼÖÐÒ²ÄÜ¿´³öÆäÖÐÐĵØÎ»£¬´úÀí¶àÏîÒµÎñ£¬¸ÃÀàÊÇÓÉAndroidShellHolder¹ý³ÌÖгõʼ»¯´´½¨µÄ£»ÁíÍâShellÀ໹¼Ì³ÐÁËServiceProtocol::Handler£¬Í¼ÖÐÊ¡ÂÔ¶øÒÑ¡£

PlatformViewAndroidÀࣺÔÚAndroidƽ̨ÉÏPlatformViewµÄʵÀý²ÉÓõıãÊÇPlatformViewAndroidÀà¡£

Dart²ãÓëC²ãÖ®¼ä¿ÉÒÔÏ໥µ÷Ó㬴ÓWindowһ·Äܵ÷Óõ½ShellÀ࣬ҲÄÜ´ÓShellÀàһ·µ÷ÓûØWindow¡£

½ÓÏÂÀ´´ø×Å´ó¼Ò´ÓÔ´Âë½Ç¶ÈÀ´ÒÀ´Î½²½âVsync×¢²áÒÔ¼°UIÏ̵߳ĻæÖÆ´¦ÀíÁ÷³Ì£¬ÏÂһƪÎÄÕ»á½éÉÜGPUÏ̵߳ĻæÖƹ¤×÷¡£

¶þ¡¢ VSYNC×¢²áÁ÷³Ì

2.1 Engine::ScheduleFrame

[-> flutter/shell/common/engine.cc]

void Engine::ScheduleFrame
(bool regenerate_layer_tree) {
//[¼ûС½Ú2.2]
animator_->RequestFrame
(regenerate_layer_tree);
}

¸Ã·½·¨ËµÃ÷£º

animator_µÄ¸³Öµ¹ý³ÌÊÇÔÚEngine¶ÔÏó³õʼ»¯¹ý³ÌÍê³É£¬¶øEngine³õʼ»¯¹ý³ÌÔÚShell´´½¨¹ý³Ì£¬´Ë´¦animator_±ãÊÇAnimator¶ÔÏó£»

ScheduleFrameµÄ²ÎÊýregenerate_layer_tree¾ö¶¨ÊÇ·ñÐèÒªÖØÐÂÉú³Élayer tree£¬»¹ÊÇÖ±½Ó¸´ÓÃÉÏÒ»´ÎÉú³ÉµÄlayer tree£»

¾ø´ó¶àÊýÇé¿öÏ£¬µ÷ÓÃRequestFrame()ʱ½«regenerate_layer_tree_ÉèÖÃΪtrue»òÕßÓÃĬÈÏÖµtrue£¬Ö´ÐÐÍêAnimator::BeginFrame()ÔòÉèÖøñäÁ¿Îªfalse£»

µ±ÎÞ²ÎÊýµ÷Óø÷½·¨Ê±£¬regenerate_layer_treeΪĬÈÏֵΪtrue¡£

ÌØ±ðµÄÀý×Ó¾ÍÊÇShell::OnPlatformViewMarkTextureFrameAvailable()¹ý³Ì£¬ÉèÖòÎÊýΪfalse£¬ÄÇô¼Æ»®»æÖÆÒ»Ö¡µÄʱºò¾Í²»ÐèÒªÖØ»ælayer tree£»

2.2 Animator::RequestFrame

[-> flutter/shell/common/animator.cc]

void Animator::RequestFrame
(bool regenerate_layer_tree) {
if (regenerate_layer_tree) {
// regenerate_layer_tree_¾ö¶¨
VsyncÐźŵ½À´Ê±£¬ÊÇ·ñÖ´ÐÐBeginFrame
regenerate_layer_tree_ = true;
}
//µ±µ÷ÓÃAnimator::Stop()
Ôò»áÍ£Ö¹¶¯»­»æÖÆ
if (paused_ &&
!dimension_change_pending_) {
return;
}
//µ÷ÓÃsem_trywaitÀ´±£Ö¤²»»áͬʱ
Óжà¸övsyncÇëÇó
if (!pending_frame_semaphore_.
TryWait()) {
return;
}
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(); // [¼ûС½Ú2.3]
});
frame_scheduled_ = true;
//±ê×¢ÒѾ­schedule»æ»­Ö¡
}

¹ý³Ì˵Ã÷£º

pending_frame_semaphore_£º·Ç¸ºÐźÅÁ¿£¬³õʼֵΪ1£¬µÚÒ»´Îµ÷ÓÃTryWait¼õ1£¬¶øºóÔٴε÷ÓÃÔò»áʧ°ÜÖ±½Ó·µ»Ø¡£µ±Ïû·ÑÁËÕâ´Îvsync»Øµ÷£¬Ò²¾ÍÊǵ÷ÓÃÁËAnimatorµÄBeginFrame()»òÕßDrawLastLayerTree()·½·¨ºó£¬¸ÄÐźÅÁ¿»á¼Ó1[¼ûС½Ú3.6]£¬¿ÉÒÔÔÙ´ÎÖ´ÐÐvysncµÄ×¢²á£»

ͨ¹ýAnimatorµÄStart()»òÕßBeginFrameµ÷Óõ½µÄRequestFrame·½·¨£¬Ôò¿Ï¶¨ÐèÒªÖØÐÂÉú³Élayer tree£»Í¨¹ýEngineµÄScheduleFrame·½·¨ÊÇ·ñÖØ½¨layer tree¿´Ð¡½Ú2.1£»

´Ë´¦Í¨¹ýpost°ÑAnimator::AwaitVSyncÈÎÎñ·ÅÈëµ½UI Task RunnerÀ´Ö´ÐС£

2.3 Animator::AwaitVSync

[-> flutter/shell/common/animator.cc]

void Animator::AwaitVSync() {
// [¼ûС½Ú2.4]
waiter_->AsyncWaitForVsync(
[self = weak_factory_.GetWeakPtr()]
(fml::TimePoint frame_start_time,
fml::TimePoint frame_target_time) {
if (self) {
//ÊÇ·ñÄܸ´ÓÃÉÏ´ÎlayerÊ÷£¬
È¡¾öÓÚregenerate_layer_tree_
if (self->CanReuseLastLayerTree()) {
//¸´ÓÃÉÏ´ÎlayerÊ÷£¬Ö±½Ó°ÑÈÎÎñpostµ½
gpuÏß³Ì×öÕ¤¸ñ»¯²Ù×÷
self->DrawLastLayerTree();
} else {
self->BeginFrame(frame_start_time,
frame_target_time);
}
}
});
delegate_.OnAnimatorNotifyIdle
(dart_frame_deadline_);
}

waiter_µÄ¸³ÖµÊÇÔÚAnimator³õʼ»¯¹ý³Ì£¬È¡ÖµÎªVsyncWaiterAndroid¶ÔÏ󣬵±µ÷ÓÃÁËRequestFrame()£¬Ä¬ÈϲÎÊýregenerate_layer_tree_Ϊtrue£¬Òâζ×ÅÐèÒªÖØÐÂÉú³ÉlayerÊ÷£¬¹Ê²»ÄÜÖØ¸´Ê¹ÓÃÉÏÒ»´ÎµÄlayerÊ÷£¬½Ó×ÅÀ´¿´Ò»ÏÂAsyncWaitForVsync()·½·¨µÄʵÏÖ¡£

2.4 VsyncWaiter::AsyncWaitForVsync

[-> flutter/shell/common/vsync_waiter.cc]

void VsyncWaiter::AsyncWaitForVsync
(Callback callback) {
{
std::lock_guard<std::mutex>
lock(callback_mutex_);
//¸³Öµcallback_
callback_ = std::move(callback);
}
TRACE_EVENT0("flutter",
"AsyncWaitForVsync");
AwaitVSync(); // [¼ûС½Ú2.5]
}

´Ë´ÎµÄcallback_±ãÊÇ[С½Ú2.3]·½·¨ÖеIJÎÊý£¬¸Ã·½·¨¸ù¾Ýregenerate_layer_tree_À´¾ö¶¨Ö´ÐÐÁ÷¡£

µ±regenerate_layer_tree_=false£¬ÔòÖ´ÐÐDrawLastLayerTree();

µ±regenerate_layer_tree_=false£¬ÔòÖ´ÐÐBeginFrame();

2.5 VsyncWaiterAndroid::AwaitVSync

[-> flutter/shell/platform/android/vsync_waiter_android.cc]

void VsyncWaiterAndroid::
AwaitVSync() {
std::weak_ptr<VsyncWaiter>*
weak_this =
new std::weak_ptr<VsyncWaiter>
(shared_from_this());
//»ñÈ¡VsyncWaiterµÄÈõÒýÓÃ
jlong java_baton = reinterpret
_cast<jlong>(weak_this);
JNIEnv* env = fml::jni::
AttachCurrentThread();
// ´Ë´Îµ÷Óõ½Java²ãµÄ
asyncWaitForVsync·½·¨£¬java_baton
Ö¸ÏòVsyncWaiter
env->CallStaticVoidMethod
(g_vsync_waiter_class->obj(), //
g_async_wait_for_vsync_method_, //
java_baton //
);
}

´Ë´¦g_vsync_waiter_class£¬g_async_wait_for_vsync_method_µÄ¸³Öµ¹ý³ÌÊÇÓÉJNI_OnLoadÍê³É£¬ÈçÏÂËùʾ¡£

2.5.1 JNI_OnLoad

[-> flutter/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 = shell::FlutterMain::
Register(env);
// ×¢²áPlatformView [¼ûС½Ú2.5.2]
result = shell::PlatformViewAndroid
::Register(env);
// ×¢²áVSyncWaiter [¼ûС½Ú2.5.3]
result = shell::VsyncWaiterAndroid
::Register(env);
return JNI_VERSION_1_4;
}

Ê״μÓÔØ¹²Ïí¿âʱÐéÄâ»ú»áµ÷Óô˷½·¨¡£

2.5.2 Register

[-> flutter/shell/platform/android/platform_view_android_jni.cc]

bool PlatformViewAndroid::
Register(JNIEnv* env) {
//¼Ç¼FlutterCallbackInformation
ÀàµÄÈ«¾ÖÒýÓÃ
g_flutter_callback_info_class = new fml::jni::ScopedJavaGlobalRef<jclass>(
env, env->FindClass("io/flutter/view
/FlutterCallbackInformation"));
//¼Ç¼FlutterCallbackInformation¹¹Ô캯Êý
g_flutter_callback_info_constructor
= env->GetMethodID(
g_flutter_callback_info_class->obj(),
"<init>",
"(Ljava/lang/String;Ljava/lang/String;
Ljava/lang/String;)V");
//¼Ç¼FlutterJNIÀàµÄÈ«¾ÖÒýÓÃ
g_flutter_jni_class = new fml::jni::ScopedJavaGlobalRef<jclass>(
env, env->FindClass("io/flutter/embedding
/engine/FlutterJNI"));
//¼Ç¼SurfaceTextureÀàµÄÈ«¾ÖÒýÓÃ
g_surface_texture_class = new fml::jni::ScopedJavaGlobalRef<jclass>(
env, env->FindClass
("android/graphics/SurfaceTexture"));
static const JNINativeMethod
callback_info_methods[] = {
{
.name = "nativeLookupCallbackInformation",
.signature = "(J)Lio/flutter/view
/FlutterCallbackInformation;",
.fnPtr = reinterpret_cast<void*>
(&shell::LookupCallbackInformation),
},
};
//×¢²áFlutterCallbackInformationµÄnativeLookupCallbackInformation()·½·¨
env->RegisterNatives
(g_flutter_callback_info_class->obj(),
callback_info_methods,
arraysize(callback_info_methods)) != 0);


g_is_released_method =
env->GetMethodID
(g_surface_texture_class->obj(),
"isReleased", "()Z");


fml::jni::ClearException(env);
g_attach_to_gl_context_method
= env->GetMethodID(
g_surface_texture_class->obj(),
"attachToGLContext", "(I)V");
g_update_tex_image_method =
env->GetMethodID
(g_surface_texture_class->obj(),
"updateTexImage", "()V");
g_get_transform_matrix_method
= env->GetMethodID(
g_surface_texture_class->obj(),
"getTransformMatrix", "([F)V");
g_detach_from_gl_context_method
= env->GetMethodID(
g_surface_texture_class->obj(),
"detachFromGLContext", "()V");
return RegisterApi(env);
}

¸Ã·½·¨µÄÖ÷Òª¹¤×÷£º

¼Ç¼ºÍ×¢²áÀàFlutterCallbackInformation¡¢FlutterJNIÒÔ¼°SurfaceTextureÀàµÄÏà¹Ø·½·¨£¬ÓÃÓÚJavaºÍC++²ã·½·¨µÄÏ໥µ÷Óá£

2.5.3 Register

[-> flutter/shell/platform/android/vsync_waiter_android.cc]

bool VsyncWaiterAndroid::Register
(JNIEnv* env) {
static const JNINativeMethod
methods[] = ;
jclass clazz = env->FindClass
("io/flutter/view/VsyncWaiter");
g_vsync_waiter_class = new fml::jni
::ScopedJavaGlobalRef
<jclass>(env, clazz);
g_async_wait_for_vsync_method_
= env->GetStaticMethodID(
g_vsync_waiter_class->obj(),
"asyncWaitForVsync", "(J)V");
return env->RegisterNatives
(clazz, methods,
arraysize(methods)) == 0;
}

¸Ã×¢²á¹ý³ÌÖ÷Òª¹¤×÷£º

½«Java²ãµÄVsyncWaiterÀàµÄnativeOnVsync()·½·¨£¬Ó³Éäµ½C++²ãµÄOnNativeVsync()·½·¨£¬ÓÃÓڸ÷½·¨µÄJavaµ÷ÓÃC++µÄ¹ý³Ì£»

½«Java²ãµÄVsyncWaiterÀàµÄasyncWaitForVsync()·½·¨£¬±£´æµ½C++²ãµÄg_async_wait_for_vsync_method_±äÁ¿£¬ÓÃÓڸ÷½·¨C++µ÷ÓÃJavaµÄ¹ý³Ì¡£

¿É¼û£¬½«µ÷ÓÃVsyncWaiterÀàµÄasyncWaitForVsync()·½·¨

2.6 asyncWaitForVsync[Java]

[-> flutter/shell/platform/android/io/flutter/view/VsyncWaiter.java]

public class VsyncWaiter {
// FlutterViewµÄË¢ÐÂʱ¼äÖÜÆÚ£¨16.7ms£©
public static long refreshPeriodNanos
= 1000000000 / 60;
private static HandlerThread
handlerThread;
private static Handler handler;
static {
handlerThread = new HandlerThread
("FlutterVsyncThread");
handlerThread.start();
}
public static void asyncWaitForVsync
(final long cookie) {
if (handler == null) {
handler = new Handler
(handlerThread.getLooper());
}
handler.post(new Runnable() {
@Override
public void run() {
//×¢²áÖ¡»Øµ÷·½·¨£¬¼ûС½Ú[2.6.1]/[2.6.2]
Choreographer.getInstance().
postFrameCallback
(new Choreographer.FrameCallback() {
@Override
public void doFrame
(long frameTimeNanos) {
//frameTimeNanosÊÇVYSNC´¥·¢µÄʱ¼äµã£¬
Ò²¾ÍÊǼƻ®»æÖƵÄʱ¼äµã
nativeOnVsync(frameTimeNanos,
frameTimeNanos +
refreshPeriodNanos, cookie);
}
});
}
});
}
}

ͨ¹ýHandler½«¹¤×÷postµ½FlutterVsyncThreadỊ̈߳¬¾ßÌåµÄ¹¤×÷ÊÇͨ¹ýChoreographerÀ´×¢²á»Øµ÷·½·¨doFrame()ÒÔ¼àÌýϵͳVSYNCÐźš£

2.6.1 Choreographer.getInstance

[-> Choreographer.java]

public static Choreographer
getInstance() {
return sThreadInstance.get();
//µ¥Àýģʽ
}
private static final ThreadLocal
<Choreographer> sThreadInstance =
new ThreadLocal<Choreographer>() {
protected Choreographer initialValue(){
//»ñÈ¡µ±Ç°Ïß³ÌFlutterVsyncThreadµÄLooper
Looper looper = Looper.myLooper();
// ³õʼ»¯Choreographer¶ÔÏó
return new Choreographer(looper);
}
};
private Choreographer(Looper looper) {
mLooper = looper;
//´´½¨Handler¶ÔÏó
mHandler = new FrameHandler(looper);
//´´½¨ÓÃÓÚ½ÓÊÕVSyncÐźŵĶÔÏó
mDisplayEventReceiver = USE_VSYNC ? new FrameDisplayEventReceiver(looper) : null;
mLastFrameTimeNanos = Long.MIN_VALUE;
//ÉÏÒ»´ÎÖ¡»æÖÆÊ±¼äµã
mFrameIntervalNanos = (long)(1000000000 / getRefreshRate());
mCallbackQueues = new CallbackQueue
[CALLBACK_LAST + 1];
for (int i = 0; i <= CALLBACK_LAST; i++){
mCallbackQueues[i] = new CallbackQueue();
}
}

´Ë´¦ChoreographerµÄmLooperºÍmHandler¶¼ÔËÐÐÔÚFlutterVsyncThreadÏ̡߳£

2.6.2 postFrameCallback

[-> Choreographer.java]

public void postFrameCallback
(FrameCallback callback) {
postFrameCallbackDelayed(callback, 0);
}
public void postFrameCallback
Delayed(FrameCallback callback,
long delayMillis) {
postCallbackDelayedInternal
(CALLBACK_ANIMATION,
callback, FRAME_CALLBACK_TOKEN,
delayMillis);
}
private void postCallbackDelayedInternal
(int callbackType, Object action,
Object token, long delayMillis) {
synchronized (mLock) {
final long now = SystemClock.
uptimeMillis();
final long dueTime = now + delayMillis;
//Ìí¼Óµ½mCallbackQueues¶ÓÁÐ
mCallbackQueues[callbackType].
addCallbackLocked
(dueTime, action, token);
if (dueTime <= now) {
scheduleFrameLocked(now);
} else {
...
}
}
}

½«FrameCallback·½·¨¼ÓÈëµ½mCallbackQueues[CALLBACK_ANIMATION]»Øµ÷¶ÓÁÐÖС£

Èý¡¢Engine²ã»æÖÆ

3.1 doFrame

[-> Choreographer.java]

public void doFrame
(long frameTimeNanos) {
//Android FWÿ´Îµ±vsyncÐźŴ¥·¢£¬
Ôò»áµ÷Óø÷½·¨ [¼ûÏ·½]
nativeOnVsync(frameTimeNanos,
frameTimeNanos +
refreshPeriodNanos, cookie);
}

Vsync×¢²á¹ý³Ì¼û[С½Ú2.6] Choreographer.FrameCallback()¡£×¢²áÁËVysncÐźźó£¬Ò»µ©µ×²ãVsyncÐźŴ¥·¢£¬¾­¹ý²ã²ãµ÷Óûص½FrameDisplayEventReceiverµÄ¹ý³Ì£¬È»ºó»áÓÐÒ»¸öͨ¹ýhandlerµÄ·½Ê½postµ½Ï̡߳±FlutterVsyncThread¡±À´Ö´ÐвÙ×÷£¬ ¾ßÌåÁ÷³Ì¼ûChoreographerÔ­Àí¡£½ô½Ó×ÅÔÙ´¦ÀíËùÓÐ×¢²áµÄdoCallbacks·½·¨£¬Ôò»áÖ´ÐÐChoreographer.FrameCallbackÖеÄdoFrame()·½·¨£¬ÈçÏÂËùʾ¡£

new Choreographer.FrameCallback(){
@Override
public void doFrame
(long frameTimeNanos) {
//frameTimeNanosÊÇVYSNC´¥·¢µÄʱ¼äµã£¬
Ò²¾ÍÊǼƻ®»æÖƵÄʱ¼äµã [¼ûС½Ú3.2]
nativeOnVsync(frameTimeNanos,
frameTimeNanos + refreshPeriodNanos,
cookie);
}
}

3.2 OnNativeVsync

[-> flutter/shell/platform/android/io/flutter/view/VsyncWaiter.java]

public class VsyncWaiter {
...
// [¼ûС½Ú3.2.1]
private static native void
nativeOnVsync(long frameTimeNanos,
long frameTargetTimeNanos,
long cookie);
...
}

ÓÉ[С½Ú2.5.3]¿ÉÖª£¬VsyncWaiter.javaÖеÄ
nativeOnVsync¶ÔÓ¦ÓÚvsync_waiter_android.cc
µÄOnNativeVsync()£¬¾ßÌå¹ý³ÌÔÚjni¼ÓÔØ¹ý³Ì³õʼ»¯£¬ÈçÏÂËùʾ¡£

3.2.1 OnNativeVsync[C++]

[-> flutter/shell/platform/android/vsync_waiter_android.cc]

static void OnNativeVsync
(JNIEnv* env, jclass jcaller,
jlong frameTimeNanos,
jlong frameTargetTimeNanos,
jlong java_baton) {
auto frame_time = fml::
TimePoint::FromEpochDelta(
fml::TimeDelta::FromNanoseconds
(frameTimeNanos));
auto target_time = fml::TimePoint
::FromEpochDelta(
fml::TimeDelta::FromNanoseconds
(frameTargetTimeNanos));
//Ïû·Ñpending»Øµ÷[¼ûС½Ú3.3]
ConsumePendingCallback
(java_baton, frame_time, target_time);
}

3.3 ConsumePendingCallback

[-> flutter/shell/platform/android/vsync_waiter_android.cc]

static void ConsumePendingCallback
(jlong java_baton,
fml::TimePoint frame_start_time,
fml::TimePoint frame_target_time) {
auto* weak_this =
reinterpret_cast<std::weak_ptr
<VsyncWaiter>*>(java_baton);
auto shared_this = weak_this->lock();
delete weak_this;
if (shared_this) {
//shared_thisÖ¸ÏòVsyncWaiterµÄÈõÒýÓÃ
[¼ûС½Ú3.4]
shared_this->FireCallback
(frame_start_time, frame_target_time);
}
}

3.4 VsyncWaiter::FireCallback

[-> flutter/shell/common/vsync_waiter.cc]

void VsyncWaiter::FireCallback
(fml::TimePoint frame_start_time,
fml::TimePoint frame_target_time) {
Callback callback;
{
std::lock_guard<std::mutex> lock
(callback_mutex_);
callback = std::move(callback_);
}
if (!callback) {
TRACE_EVENT_INSTANT0("flutter",
"MismatchedFrameCallback");
return;
}
TRACE_EVENT0("flutter",
"VsyncFireCallback");
//½«ÈÎÎñ·ÅÈëtask¶ÓÁÐ[¼ûС½Ú3.4.1]
task_runners_.GetUITaskRunner()
->PostTaskForTime(
[callback, flow_identifier,
frame_start_time,
frame_target_time]() {
FML_TRACE_EVENT("flutter",
kVsyncTraceName, "StartTime",
frame_start_time, "TargetTime",
frame_target_time);
fml::tracing::TraceEventAsyncComplete(
"flutter", "VsyncSchedulingOverhead",
fml::TimePoint::Now(),
frame_start_time);
//¿ªÊ¼Ö´ÐÐvync [¼ûС½Ú3.5]
callback(frame_start_time,
frame_target_time);
TRACE_FLOW_END("flutter",
kVsyncFlowName, flow_identifier);
},
frame_start_time);
}

½«ÈÎÎñ±Õ°ü·ÅÈëtask¶ÓÁУ¬ÏûÏ¢LoopÒ»µ©½ÓÊܵ½ÏûÏ¢Ôò»á¶ÁÈ¡³öÀ´¡£

3.4.1 MessageLoopImpl::RunExpiredTasks

[-> flutter/fml/message_loop_impl.cc]

void MessageLoopImpl::
RunExpiredTasks() {
TRACE_EVENT0("fml", "MessageLoop
::RunExpiredTasks");
std::vector<fml::closure>
invocations;
{
std::lock_guard<std::mutex>
lock(delayed_tasks_mutex_);
//µ±Ã»Óдý´¦ÀíµÄtaskÔòÖ±½Ó·µ»Ø
if (delayed_tasks_.empty()) {
return;
}
auto now = fml::TimePoint::Now();
while (!delayed_tasks_.empty()) {
const auto& top
= delayed_tasks_.top();
if (top.target_time > now) {
break;
}
invocations.emplace_back
(std::move(top.task));
delayed_tasks_.pop();
}
WakeUp(delayed_tasks_.empty() ?
fml::TimePoint::Max()
: delayed_tasks_.top().target_time);
}
for (const auto& invocation
: invocations) {
invocation(); // [¼ûС½Ú3.5]
for (const auto& observer
: task_observers_) {
observer.second();
}
}
}

¶ÔÓÚuiÏ̴߳¦ÓÚÏûÏ¢loop״̬£¬Ò»µ©ÓÐʱ¼äµ½´ïµÄÈÎÎñÔò¿ªÊ¼Ö´ÐУ¬·ñÔò´¦ÓÚ¿ÕÏеȵÈ״̬¡£Ç°Ãæ[С½Ú3.4] VsyncWaiter::FireCallback¹ý³ÌÒѾ­Ïò¸ÃuiÏß³ÌpostTask¡£ ¶ÔÓÚ²»¿É¸´ÓÃlayer treeµÄÇé¿öÔòµ÷ÓÃAnimator::BeginFrame()·½·¨¡£

3.5 callback

[-> flutter/shell/common/animator.cc]

[self = weak_factory_.GetWeakPtr()]
(fml::TimePoint frame_start_time,
fml::TimePoint frame_target_time) {
if (self) {
if (self->CanReuseLastLayerTree()) {
self->DrawLastLayerTree();
} else {
//¸ù¾ÝĬÈϲÎÊýregenerate_layer_tree_
Ϊtrue£¬ÔòÖ´Ðи÷ÖÖ§ [¼ûС½Ú3.6]
self->BeginFrame(frame_start_time,
frame_target_time);
}
}
}

´Ë´ÎµÄcallback¸³Öµ¹ý³ÌλÓÚ[С½Ú2.3]Animator::AwaitVSync()·½·¨µÄ±Õ°ü²ÎÊý£¬Ïà¹ØËµÃ÷£º

frame_start_time£º¼Æ»®¿ªÊ¼»æÖÆÊ±¼äµã£¬À´Ô´ÓÚdoFrame()·½·¨ÖеIJÎÊý£»

frame_target_time£º´Óframe_start_time¼ÓÉÏһ֡ʱ¼ä(16.7ms)µÄʱ¼ä£¬×÷Ϊ±¾´Î»æÖƵÄdeadline¡£

3.6 Animator::BeginFrame

[-> flutter/shell/common/animator.cc]

void Animator::BeginFrame
(fml::TimePoint frame_start_time,
fml::TimePoint frame_target_time) {
TRACE_EVENT_ASYNC_END0("flutter",
"Frame Request Pending", frame_number_++);
TRACE_EVENT0("flutter",
"Animator::BeginFrame");
frame_scheduled_ = false;
notify_idle_task_id_++;
regenerate_layer_tree_ = false;
//ÐźÅÁ¿¼Ó1£¬¿ÉÒÔ×¢²áеÄvsyncÐźţ¬
Ò²¾ÍÊÇÄÜÖ´ÐÐAnimator::RequestFrame()
pending_frame_semaphore_.Signal();
if (!producer_continuation_) {
//[С½Ú3.6.1]/[С½Ú3.6.2]
producer_continuation_
= layer_tree_pipeline_->Produce();
//pipelineÒÑÂú£¬ËµÃ÷GPUÏ̷߳±Ã¦£¬
Ôò½áÊø±¾´ÎUI»æÖÆ£¬ÖØÐÂ×¢²áVsync
if (!producer_continuation_) {
RequestFrame();
return;
}
}
//´ÓpipelineÖлñÈ¡ÓÐЧµÄcontinuation£¬
²¢×¼±¸Îª¿ÉÄܵÄframe·þÎñ
last_begin_frame_time_
= frame_start_time;
//»ñÈ¡µ±Ç°Ö¡»æÖƽØÖ¹Ê±¼ä£¬
ÓÃÓÚ¸æÖª¿ÉGCµÄ¿ÕÏÐʱ³¤
dart_frame_deadline_
= FxlToDartOrEarlier
(frame_target_time);
{
TRACE_EVENT2("flutter",
"Framework Workload", "mode",
"basic", "frame",
FrameParity());
//´Ë´¦delegate_ΪShell [С½Ú3.7]
delegate_.OnAnimatorBeginFrame
(last_begin_frame_time_);
}
if (!frame_scheduled_) {
task_runners_.GetUITaskRunner()
->PostDelayedTask(
[self = weak_factory_.GetWeakPtr(),
notify_idle_task_id
= notify_idle_task_id_]() {
if (!self.get()) {
return;
}
// ¸ÃÈÎÎñidºÍµ±Ç°ÈÎÎñidÒ»Ö£¬
Ôò²»ÔÙÐèÒªÉó²éframe£¬
¿ÉÒÔ֪ͨÒýÇæµ±Ç°´¦ÓÚ¿ÕÏÐ״̬£¬100ms
if (notify_idle_task_id ==
self->notify_idle_task_id_) {
self->delegate_.OnAnimatorNotifyIdle
(Dart_TimelineGetMicros() +
100000);
}
},
kNotifyIdleTaskWaitTime);
//ÑÓ³Ù51msÔÙ֪ͨÒýÇæ¿ÕÏÐ״̬
}
}

¸Ã·½·¨Ö÷Òª¹¦ÄÜ˵Ã÷£º

layer_tree_pipeline_ÊÇÔÚAnimator¶ÔÏó³õʼ»¯µÄ¹ý³ÌÖд´½¨µÄLayerTreePipeline£¬ÆäÀàÐÍΪPipeline

´Ë´¦kNotifyIdleTaskWaitTimeµÈÓÚ51ms£¬µÈÓÚ3Ö¡µÄʱ¼ä+1ms£¬Ö®ËùÒÔÕâÑùÉè¼ÆÊÇÓÉÓÚÔÚijЩ¹¤×÷¸ºÔØÏ£¨±ÈÈ縸ÊÓͼµ÷Õû´óС£¬Í¨¹ýviewport metricsʼþ´«´ï¸ø×ÓÊÓͼ£©Êµ¼ÊÉÏ»¹Ã»ÓÐscheduleÖ¡£¬¾¡¹ÜÔÚÏÂÒ»¸övsync»áÉú³ÉÒ»Ö¡(½«ÔÚÊÕµ½viewportʼþºóschedule)£¬Òò´ËÍÆ³Ùµ÷ÓÃOnAnimatorNotifyIdleÒ»µãµã£¬´Ó¶ø±ÜÃâ¿ÉÄÜÀ¬»ø»ØÊÕÔÚ²»Ï£ÍûµÄʱ¼ä´¥·¢¡£

3.6.1 LayerTreePipeline³õʼ»¯

[-> flutter/shell/common/animator.cc]

Animator::Animator(Delegate& delegate,
TaskRunners task_runners,
std::unique_ptr<VsyncWaiter> waiter)
: delegate_(delegate),
task_runners_(std::move(task_runners)),
waiter_(std::move(waiter)),
last_begin_frame_time_(),
dart_frame_deadline_(0),
layer_tree_pipeline_(fml
::MakeRefCounted<LayerTreePipeline>(2)),
... {}

´Ë´¦LayerTreePipelineµÄ³õʼ»¯¹ý³ÌÈçÏ£º

using LayerTreePipeline
= Pipeline<flutter::LayerTree>;

ÔÚpipeline.hµÄ¹ý³Ì»á³õʼ»¯Pipeline£¬¿É¼û³õʼֵempty_ = 2£¬available_ = 0£»

Pipeline(uint32_t depth) :
empty_(depth), available_(0) {}

3.6.2 Pipeline::Produce

[-> flutter/synchronization/pipeline.h]

ProducerContinuation Produce() {
//µ±¹ÜµÀ²»Îª¿Õ£¬
Ôò²»ÔÊÐíÔÙ´ÎÏò¹ÜµÀ¼ÓÈëÊý¾Ý
if (!empty_.TryWait()) {
return {};
}
//[¼ûС½Ú3.6.3]
return ProducerContinuation{
std::bind(&Pipeline::ProducerCommit,this, std::placeholders::_1,
std::placeholders::_2), // continuation
GetNextPipelineTraceID()};
}

ͨ¹ýÐźÅÁ¿empty_µÄ³õʼֵΪdepth(ĬÈϵÈÓÚ2)£¬À´±£Ö¤Í¬Ò»¸ö¹ÜµÀµÄÈÎÎñ×î¶à²»³¬¹ýdepth¸ö£¬Ã¿´ÎUIÏß³ÌÖ´ÐÐProduce()»á¼õ1£¬µ±GPUÏß³ÌÖ´ÐÐÍê³ÉConsume()·½·¨ºó²Å»áÖ´ÐмÓ1²Ù×÷¡£

3.6.3 ProducerContinuation³õʼ»¯

[-> flutter/synchronization/pipeline.h]

ProducerContinuation
(Continuation continuation,
size_t trace_id)
: continuation_(continuation),
trace_id_(trace_id) {
TRACE_FLOW_BEGIN("flutter",
"PipelineItem", trace_id_);
TRACE_EVENT_ASYNC_BEGIN0
("flutter", "PipelineProduce",
trace_id_);
}

3.6.3 Pipeline.ProducerCommit

[-> flutter/synchronization/pipeline.h]

void ProducerCommit
(ResourcePtr resource,
size_t trace_id) {
{
std::lock_guard<std::mutex>
lock(queue_mutex_);
queue_.emplace(std::move
(resource), trace_id);
}
available_.Signal();
}

3.7 Shell::OnAnimatorBeginFrame

[-> flutter/shell/common/shell.cc]

void Shell::OnAnimatorBeginFrame
(fml::TimePoint frame_time) {
if (engine_) {
engine_->BeginFrame(frame_time);
// [С½Ú3.8]
}
}

3.8 Engine::BeginFrame

[-> flutter/shell/common/engine.cc]

void Engine::BeginFrame
(fml::TimePoint frame_time) {
TRACE_EVENT0("flutter",
"Engine::BeginFrame");
runtime_controller_
->BeginFrame(frame_time);
// [С½Ú3.9]
}

3.9 RuntimeController::BeginFrame

[-> flutter/runtime/runtime_controller.cc]

bool RuntimeController::BeginFrame
(fml::TimePoint frame_time) {
if (auto* window =
GetWindowIfAvailable()) {
window->BeginFrame(frame_time);
// [С½Ú3.10]
return true;
}
return false;
}

3.10 Window::BeginFrame

[-> flutter/lib/ui/window/window.cc]

void Window::BeginFrame
(fml::TimePoint frameTime) {
std::shared_ptr<tonic::DartState>
dart_state = library_.
dart_state().lock();
if (!dart_state)
return;
tonic::DartState::Scope scope
(dart_state);
//×¢Òâ´Ë´¦µÄframeTime±ãÊÇÇ°Ãæ
С½Ú3.1ÖÐdoFrame·½·¨ÖÐ
µÄ²ÎÊýframeTimeNanos
int64_t microseconds = (frameTime - fml::TimePoint()).ToMicroseconds();
// [¼ûС½Ú4.2]
DartInvokeField(library_.value(),
"_beginFrame",
{Dart_NewInteger(microseconds)});
//Ö´ÐÐMicroTask
UIDartState::Current()
->FlushMicrotasksNow();
// [¼ûС½Ú4.4]
DartInvokeField(library_.value(),
"_drawFrame", {});
}

Window::BeginFrame()¹ý³ÌÖ÷Òª¹¤×÷£º

Ö´ÐÐ_beginFrame

Ö´ÐÐFlushMicrotasksNow

Ö´ÐÐ_drawFrame

¿É¼û£¬MicrotaskλÓÚbeginFrameºÍdrawFrameÖ®¼ä£¬ÄÇôMicrotaskµÄºÄʱ»áÓ°Ïìui»æÖƹý³Ì¡£

DartInvokeField()ͨ¹ýdartÐéÄâ»úµ÷ÓÃÁËwindow.onBeginFrame()ºÍonDrawFrame·½·¨£¬¼ûhooks.dartÎļþÖÐÈçϹý³Ì

@pragma('vm:entry-point')
void _beginFrame
(int microseconds) {
_invoke1<Duration>
(window.onBeginFrame,
window._onBeginFrameZone,
new Duration(microseconds:
microseconds));
}
@pragma('vm:entry-point')
void _drawFrame() {
_invoke(window.onDrawFrame,
window._onDrawFrameZone);
}

ËÄ¡¢Framework²ã»æÖÆ

ÔÚÒýÇæ²ãµÄ´¦Àí¹ý³Ì»áµ÷Óõ½window.onBeginFrame()ºÍonDrawFrame£¬»Øµ½framework²ã´ÓÕâ¸öÁ½¸ö·½·¨¿ªÊ¼ËµÆð¡£

4.1 SchedulerBinding.initInstances

[-> lib/src/scheduler/binding.dart:: SchedulerBinding]

mixin SchedulerBinding on BindingBase,
ServicesBinding {
@override
void initInstances() {
super.initInstances();
_instance = this;
ui.window.onBeginFrame =
_handleBeginFrame; //[¼ûС½Ú4.2]
ui.window.onDrawFrame =
_handleDrawFrame; //[¼ûС½Ú4.4]
SystemChannels.lifecycle.
setMessageHandler
(_handleLifecycleMessage);
}
}

¿É¼û£¬ÒýÇæ²ãÖеÄWindow::BeginFrame()µ÷ÓõÄÁ½¸ö·½·¨£¬½øÈëµ½dart²ãÔò·Ö±ðÊÇ_handleBeginFrame()ºÍ_handleDrawFrame()·½·¨

4.1.1 Window³õʼ»¯

[-> flutter/lib/ui/window.dart]

class Window {
Window._()
FrameCallback get onBeginFrame
=> _onBeginFrame;
FrameCallback _onBeginFrame;
VoidCallback get onDrawFrame
=> _onDrawFrame;
VoidCallback _onDrawFrame;
...
}

Window³õʼ»¯¹ý³Ì£¬¿ÉÒÔÖªµÀonBeginFrameºÍonDrawFrame·Ö±ð±£´æ_onBeginFrameºÍ_onDrawFrame·½·¨¡£

4.2 _handleBeginFrame

[-> lib/src/scheduler/binding.dart:: SchedulerBinding]

void _handleBeginFrame
(Duration rawTimeStamp) {
if (_warmUpFrame) {
_ignoreNextEngineDrawFrame=true;
return;
}
handleBeginFrame(rawTimeStamp);
//[¼ûС½Ú4.3]
}

4.3 handleBeginFrame

[-> lib/src/scheduler/binding.dart:: SchedulerBinding]

void handleBeginFrame
(Duration rawTimeStamp) {
Timeline.startSync('Frame', arguments: timelineWhitelistArguments);
_firstRawTimeStampInEpoch ??=
rawTimeStamp;
_currentFrameTimeStamp =
_adjustForEpoch(rawTimeStamp ??
_lastRawTimeStamp);
if (rawTimeStamp != null)
_lastRawTimeStamp = rawTimeStamp;
profile(() {
_profileFrameNumber += 1;
_profileFrameStopwatch.reset();
_profileFrameStopwatch.start();
});
//´Ëʱ½×¶ÎµÈÓÚSchedulerPhase.idle;
_hasScheduledFrame = false;
try {
Timeline.startSync('Animate',
arguments: timelineWhitelistArguments);
_schedulerPhase = SchedulerPhase.
transientCallbacks;
//Ö´Ðж¯»­µÄ»Øµ÷·½·¨
final Map<int, _FrameCallbackEntry>
callbacks = _transientCallbacks;
_transientCallbacks = <int,
_FrameCallbackEntry>{};
callbacks.forEach((int id,
_FrameCallbackEntry callbackEntry) {
if (!_removedIds.contains(id))
_invokeFrameCallback
(callbackEntry.callback,
_currentFrameTimeStamp,
callbackEntry.debugStack);
});
_removedIds.clear();
} finally {
_schedulerPhase = SchedulerPhase.
midFrameMicrotasks;
}
}

¸Ã·½·¨Ö÷Òª¹¦ÄÜÊDZéÀú_transientCallbacks£¬Ö´ÐÐÏàÓ¦µÄAnimate²Ù×÷£¬¿Éͨ¹ýscheduleFrameCallback()/cancelFrameCallbackWithId()À´Íê³ÉÌí¼ÓºÍɾ³ý³ÉÔ±£¬ÔÙÀ´¼òµ¥¿´¿´ÕâÁ½¸ö·½·¨¡£

4.3.1 scheduleFrameCallback

[-> lib/src/scheduler/binding.dart:: SchedulerBinding]

int scheduleFrameCallback
(FrameCallback callback,
{ bool rescheduling = false }) {
scheduleFrame(); //´¥·¢Ö¡»æÖƵĵ÷¶È
_nextFrameCallbackId += 1;
_transientCallbacks
[_nextFrameCallbackId] =
_FrameCallbackEntry(callback,
rescheduling: rescheduling);
return _nextFrameCallbackId;
}

callback±£´æÔÚ_FrameCallbackEntry¶ÔÏóÀïÃæ

4.3.2 cancelFrameCallbackWithId

[-> lib/src/scheduler/binding.dart:: SchedulerBinding]

void cancelFrameCallbackWithId
(int id) {
assert(id > 0);
_transientCallbacks.remove(id);
_removedIds.add(id);
}

4.4 _handleDrawFrame

[-> lib/src/scheduler/binding.dart:: SchedulerBinding]

void _handleDrawFrame() {
if (_ignoreNextEngineDrawFrame) {
_ignoreNextEngineDrawFrame = false;
return;
}
handleDrawFrame(); //[¼ûС½Ú4.5]
}

4.5 handleDrawFrame

[-> lib/src/scheduler/binding.dart:: SchedulerBinding]

void handleDrawFrame() {
assert(_schedulerPhase == SchedulerPhase.midFrameMicrotasks);
Timeline.finishSync();
// ±êʶ½áÊø"Animate"½×¶Î
try {
_schedulerPhase = SchedulerPhase.
persistentCallbacks;
//Ö´ÐÐPERSISTENT FRAME»Øµ÷
for (FrameCallback callback in
_persistentCallbacks)
_invokeFrameCallback(callback,
_currentFrameTimeStamp);
//[¼ûС½Ú4.5.1]
_schedulerPhase = SchedulerPhase.
postFrameCallbacks;
// Ö´ÐÐPOST-FRAME»Øµ÷
final List<FrameCallback>
localPostFrameCallbacks
= List<FrameCallback>.from
(_postFrameCallbacks);
_postFrameCallbacks.clear();
for (FrameCallback callback in
localPostFrameCallbacks)
_invokeFrameCallback(callback,
_currentFrameTimeStamp);
} finally {
_schedulerPhase = SchedulerPhase.idle;
Timeline.finishSync();
//±êʶ½áÊø¡±Frame¡°½×¶Î
profile(() {
_profileFrameStopwatch.stop();
_profileFramePostEvent();
});
_currentFrameTimeStamp = null;
}
}

¸Ã·½·¨Ö÷Òª¹¦ÄÜ£º

±éÀú_persistentCallbacks£¬Ö´ÐÐÏàÓ¦µÄ»Øµ÷·½·¨£¬¿Éͨ¹ýaddPersistentFrameCallback()×¢²á£¬Ò»µ©×¢²áºó²»¿ÉÒÆ³ý£¬ºóÐøÃ¿Ò»´Îframe»Øµ÷¶¼»áÖ´ÐУ»

±éÀú_postFrameCallbacks£¬Ö´ÐÐÏàÓ¦µÄ»Øµ÷·½·¨£¬¿Éͨ¹ýaddPostFrameCallback()×¢²á£¬handleDrawFrame()Ö´ÐÐÍê³Éºó»áÇå¿Õ_postFrameCallbacksÄÚÈÝ¡£

4.5.1 _invokeFrameCallback

[-> lib/src/scheduler/binding.dart:: SchedulerBinding]

void _invokeFrameCallback
(FrameCallback callback,
Duration timeStamp,
[ StackTrace callbackStack ]) {
try {
callback(timeStamp); //[¼ûС½Ú4.5.2]
} catch (exception, exceptionStack){
FlutterError.reportError
(FlutterErrorDetails(...));
}
}

ÕâÀïµÄcallbackÊÇ_persistentCallbacksÁбíÖеijÉÔ±£¬ÔÙÀ´¿´¿´Æä³ÉÔ±ÊÇÈçºÎÌí¼Ó½øÈ¥µÄ¡£

4.5.2 WidgetsBinding.initInstances

[-> lib/src/widgets/binding.dart]

mixin WidgetsBinding on BindingBase,
SchedulerBinding, GestureBinding,
RendererBinding, SemanticsBinding {
@override
void initInstances() {
super.initInstances(); //[¼ûС½Ú4.5.3]
_instance = this;
buildOwner.onBuildScheduled =
_handleBuildScheduled;
ui.window.onLocaleChanged =
handleLocaleChanged;
ui.window.onAccessibilityFeaturesChanged = handleAccessibilityFeaturesChanged;
SystemChannels.navigation.
setMethodCallHandler
(_handleNavigationInvocation);
SystemChannels.system.setMessageHandler
(_handleSystemMessage);
}
}

ÔÚflutter appÆô¶¯¹ý³Ì£¬Ò²¾ÍÊÇÖ´ÐÐrunApp¹ý³Ì»áÓÐWidgetsFlutterBinding³õʼ»¯¹ý³Ì£¬WidgetsBindingµÄinitInstances()£¬¸ù¾ÝmixinµÄ˳Ðò£¬¿ÉÖª´Ë´¦µÄsuper.initInstances() ±ãÊÇRendererBindingÀà¡£

4.5.3 RendererBinding.initInstances

[-> lib/src/rendering/binding.dart]

mixin RendererBinding on
BindingBase, ServicesBinding,
SchedulerBinding, SemanticsBinding,
HitTestable {
void initInstances() {
super.initInstances();
_instance = this;
_pipelineOwner = PipelineOwner(
onNeedVisualUpdate: ensureVisualUpdate,
onSemanticsOwnerCreated:
_handleSemanticsOwnerCreated,
onSemanticsOwnerDisposed:
_handleSemanticsOwnerDisposed,
);
ui.window
..onMetricsChanged
= handleMetricsChanged
..onTextScaleFactorChanged
= handleTextScaleFactorChanged
..onSemanticsEnabledChanged
= _handleSemanticsEnabledChanged
..onSemanticsAction =
_handleSemanticsAction;
initRenderView();
_handleSemanticsEnabledChanged();
addPersistentFrameCallback
(_handlePersistentFrameCallback);
//[¼ûС½Ú4.5.4]
}
void _handlePersistentFrameCallback
(Duration timeStamp) {
drawFrame(); //[¼ûС½Ú4.6]
}
}

4.5.4 SchedulerBinding.addPersistentFrameCallback

[-> lib/src/scheduler/binding.dart]

mixin SchedulerBinding on
BindingBase, ServicesBinding {
void addPersistentFrameCallback
(FrameCallback callback) {
_persistentCallbacks.add(callback);
}
}

4.6 WidgetsBinding.drawFrame

[-> lib/src/widgets/binding.dart]

void drawFrame() {
try {
if (renderViewElement != null)
buildOwner.buildScope
(renderViewElement); //[¼ûС½Ú4.6.1]
super.drawFrame();
//[¼ûС½Ú4.6.4]
buildOwner.finalizeTree();
//[¼ûС½Ú4.12]
} finally {
}
}

4.6.1 BuildOwner.buildScope

[-> lib/src/widgets/framework.dart]

void buildScope(Element context,
[VoidCallback callback]) {
if (callback == null &&
_dirtyElements.isEmpty)
return;
Timeline.startSync('Build',
arguments: timelineWhitelistArguments);
try {
_scheduledFlushDirtyElements = true;
if (callback != null) {
_dirtyElementsNeedsResorting = false;
callback(); //Ö´Ðлص÷·½·¨
}
_dirtyElements.sort(Element._sort);
//ÅÅÐò
_dirtyElementsNeedsResorting = false;
int dirtyCount = _dirtyElements.length;
int index = 0;
while (index < dirtyCount) {
try {
//¾ßÌåElement×ÓÀàÖ´ÐÐÖØ½¨²Ù×÷
[¼ûС½Ú4.6.2]
_dirtyElements[index].rebuild();
} catch (e, stack) {
}
index += 1;
if (dirtyCount < _dirtyElements.length || _dirtyElementsNeedsResorting) {
_dirtyElements.sort(Element._sort);
_dirtyElementsNeedsResorting = false;
dirtyCount = _dirtyElements.length;
while (index > 0 && _dirtyElements
[index - 1].dirty) {
index -= 1;
}
}
}
} finally {
for (Element element in _dirtyElements){
element._inDirtyList = false;
}
_dirtyElements.clear();
_scheduledFlushDirtyElements = false;
_dirtyElementsNeedsResorting = null;
Timeline.finishSync();
}
}

4.6.2 Element.rebuild

[-> lib/src/widgets/framework.dart]

void rebuild() {
if (!_active || !_dirty)
return;
performRebuild();
}

performRebuild¾ßÌåÖ´Ðз½·¨£¬È¡¾öÓÚÏàÓ¦µÄElement×ÓÀ࣬ÕâÀïÒÔComponentElementΪÀý

4.6.3 ComponentElement.performRebuild

[-> lib/src/widgets/framework.dart]

void performRebuild() {
Widget built;
try {
built = build(); //Ö´ÐÐbuild·½·¨
} catch (e, stack) {
built = ErrorWidget.builder
(_debugReportException
('building $this', e, stack));
} finally {
_dirty = false;
}
try {
_child = updateChild
(_child, built, slot);
//¸üÐÂ×ÓÔªËØ
} catch (e, stack) {
built = ErrorWidget.builder
(_debugReportException
('building $this', e, stack));
_child = updateChild(null, built, slot);
}
}

4.6.4 RendererBinding.drawFrame

[-> lib/src/rendering/binding.dart]

void drawFrame() {
pipelineOwner.flushLayout();
//[¼ûС½Ú4.7]
pipelineOwner.flushCompositingBits();
//[¼ûС½Ú4.8]
pipelineOwner.flushPaint();
//[¼ûС½Ú4.9]
renderView.compositeFrame();
//[¼ûС½Ú4.10]
pipelineOwner.flushSemantics();
//[¼ûС½Ú4.11]
}

RendererBindingµÄinitInstances()¹ý³Ì×¢²áÁËÒ»¸öPersistentµÄÖ¡»Øµ÷·½·¨_handlePersistentFrameCallback()£¬¹ÊhandleDrawFrame()¹ý³Ì»áµ÷Óø÷½·¨¡£pipelineOwner¹ÜÀíäÖȾ¹ÜµÀ£¬ÌṩÁËÒ»¸öÓÃÓÚÇý¶¯äÖȾ¹ÜµÀµÄ½Ó¿Ú£¬²¢´æ´¢ÁËÄÄЩäÖȾ¶ÔÏóÇëÇó·ÃÎÊ״̬£¬ÒªË¢Ð¹ܵÀ£¬ÐèÒª°´Ë³ÐòÔËÐÐÈçÏÂ5¸ö½×

¶Î£º

[flushLayout]£º¸üÐÂÐèÒª¼ÆËãÆä²¼¾ÖµÄäÖȾ¶ÔÏó£¬Ôڴ˽׶μÆËãÿ¸öäÖȾ¶ÔÏóµÄ´óСºÍλÖã¬äÖȾ¶ÔÏó¿ÉÄÜ»áŪÔàÆä»æ»­»òÕߺϳÉ״̬£¬Õâ¸ö¹ý³Ì¿ÉÄÜ»¹»áµ÷Óõ½build¹ý³Ì¡£

ºÄʱ¶ÔÓ¦timelineµÄ¡®Layout¡¯¹ý³Ì

[flushCompositingBits]£º¸üоßÓÐÔàºÏ³ÉλµÄÈκÎäÖȾ¶ÔÏó£¬Ôڴ˽׶Îÿ¸öäÖȾ¶ÔÏó¶¼»áÁ˽âÆä×ÓÏîÊÇ·ñÐèÒªºÏ³É¡£ÔÚ»æÖƽ׶ÎʹÓôËÐÅϢѡÔñÈçºÎʵÏֲüôµÈÊÓ¾õЧ¹û¡£Èç¹ûäÖȾ¶ÔÏóÓÐÒ»¸ö×Ô¼ººÏ³ÉµÄ×ÓÏËüÐèҪʹÓò¼¾ÖÐÅÏ¢À´´´½¨²Ã¼ô£¬ÒԱ㽫²Ã¼ôÓ¦ÓÃÓÚÒѺϳɵÄ×ÓÏî

ºÄʱ¶ÔÓ¦timelineµÄ¡®Compositing bits¡¯¹ý³Ì

[flushPaint]£º·ÃÎÊÐèÒª»æÖƵÄÈκÎäÖȾ¶ÔÏó£¬Ôڴ˽׶Σ¬äÖȾ¶ÔÏóÓлú»á½«»æÖÆÃüÁî¼Ç¼µ½[PictureLayer]£¬²¢¹¹½¨ÆäËûºÏ³ÉµÄ[Layer]£»

ºÄʱ¶ÔÓ¦timelineµÄ¡®Paint¡¯¹ý³Ì

[compositeFrame]£º½«Compositing bits·¢Ë͸øGPU£»

ºÄʱ¶ÔÓ¦timelineµÄ¡®Compositing¡¯¹ý³Ì

[flushSemantics]£º±àÒëäÖȾ¶ÔÏóµÄÓïÒ壬²¢½«ÓïÒå·¢Ë͸ø²Ù×÷ϵͳ£»

ºÄʱ¶ÔÓ¦timelineµÄ¡®Semantics¡¯¹ý³Ì

packages/flutter/lib/src/rendering/debug.dart£¬ÕâÀïÃæ¼Ç¼×ŹØÓÚrender¹ý³ÌÏà¹ØµÄµ÷ÊÔ¿ª¹Ø£¬¿ÉÒÔÖðһʵ¼ù¡£

4.7 PipelineOwner.flushLayout

[-> lib/src/rendering/object.dart]

void flushLayout() {
profile(() {
Timeline.startSync('Layout', arguments: timelineWhitelistArguments);
});
try {
//±éÀúËùÓеÄäÖȾ¶ÔÏó
while (_nodesNeedingLayout.isNotEmpty){
final List<RenderObject>
dirtyNodes = _nodesNeedingLayout;
_nodesNeedingLayout = <RenderObject>[];
for (RenderObject node
in dirtyNodes..sort
((RenderObject a, RenderObject b)
=> a.depth - b.depth)) {
//Èç¹ûäÖȾ¶ÔÏóÐèÒªÖØÐ²¼¾Ö£¬
ÔòÖ´Ðв¼¾Ö²Ù×÷ [¼ûС½Ú4.7.1]
if (node._needsLayout &&
node.owner == this)
node._layoutWithoutResize();
}
}
} finally {
profile(() {
Timeline.finishSync();
});
}
}

4.7.1 _layoutWithoutResize

[-> lib/src/rendering/object.dart]

void _layoutWithoutResize() {
try {
performLayout(); //Ö´Ðв¼¾Ö²Ù×÷[]
markNeedsSemanticsUpdate();
//[¼ûС½Ú4.7.2]
} catch (e, stack) {
_debugReportException
('performLayout', e, stack);
}
_needsLayout = false;
//Íê³Élayout²Ù×÷
markNeedsPaint(); // [¼ûС½Ú4.7.3]
}

¸Ã·½·¨Ö÷Òª¹¤×÷£º

performLayout²Ù×÷£º²ÎÊýsizedByParentΪfalseÐèҪͬʱ¸Ä±ääÖȾ¶ÔÏóºÍÖ¸µ¼×ÓÏîµÄ²¼¾Ö£¬ÐÔÄܸüÂý£»

markNeedsSemanticsUpdate£º±ê¼ÇÐèÒª¸üÐÂÓïÒ壻

markNeedsPaint£º±ê¼ÇÐèÒª»æÖÆ£»

SchedulerBinding.scheduleWarmUpFrame
RenderView.performLayout
RenderObject.layout
_RenderLayoutBuilder.performLayout
_LayoutBuilderElement._layout
BuildOwner.buildScope

4.7.2 markNeedsSemanticsUpdate

[-> lib/src/rendering/object.dart]

void markNeedsSemanticsUpdate() {
if (!attached || owner.
_semanticsOwner == null) {
_cachedSemanticsConfiguration = null;
return;
}
final bool wasSemanticsBoundary
= _semantics != null &&
_cachedSemanticsConfiguration?.
isSemanticBoundary == true;
_cachedSemanticsConfiguration = null;
bool isEffectiveSemanticsBoundary = _semanticsConfiguration.
isSemanticBoundary && wasSemanticsBoundary;
RenderObject node = this;
while (!isEffectiveSemanticsBoundary
&& node.parent is RenderObject) {
if (node != this && node
._needsSemanticsUpdate)
break;
node._needsSemanticsUpdate = true;
node = node.parent;
isEffectiveSemanticsBoundary = node._semanticsConfiguration.
isSemanticBoundary;
if (isEffectiveSemanticsBoundary
&& node._semantics == null) {
return;
}
}
if (node != this && _semantics != null && _needsSemanticsUpdate) {
owner._nodesNeedingSemantics.
remove(this);
}
if (!node._needsSemanticsUpdate) {
node._needsSemanticsUpdate = true;
if (owner != null) {
//¼Ç¼ÐèÒª¸üÐÂÓïÒåµÄäÖȾ¶ÔÏó
owner._nodesNeedingSemantics.add(node);
owner.requestVisualUpdate();
}
}
}

4.7.3 markNeedsPaint

[-> lib/src/rendering/object.dart]

void markNeedsPaint() {
if (_needsPaint)
return;
_needsPaint = true;
if (isRepaintBoundary) {
if (owner != null) {
//¼Ç¼ÐèÒªÖØÐ»æÖƵÄäÖȾ¶ÔÏó
owner._nodesNeedingPaint.add(this);
owner.requestVisualUpdate();
}
} else if (parent is RenderObject){
final RenderObject parent
= this.parent;
parent.markNeedsPaint();
} else {
if (owner != null)
owner.requestVisualUpdate();
}
}

4.8 PipelineOwner.flushCompositingBits

[-> lib/src/rendering/object.dart]

void flushCompositingBits() {
profile(() { Timeline.startSync
('Compositing bits'); });
_nodesNeedingCompositingBitsUpdate.
sort((RenderObject a, RenderObject b)
=> a.depth - b.depth);
for (RenderObject node in _nodesNeedingCompositingBitsUpdate) {
//¸ù¾ÝÐèÒªÀ´¾ö¶¨ÊÇ·ñ¸üÐÂλºÏ³É
if (node._needsCompositingBitsUpdate
&& node.owner == this)
node._updateCompositingBits();
// [¼ûС½Ú4.8.1]
}
_nodesNeedingCompositingBitsUpdate.clear();
//Çå¿ÕÐèҪλºÏ³ÉµÄäÖȾ¶ÔÏó
profile(() { Timeline.finishSync(); });
}

4.8.1 _updateCompositingBits

[-> lib/src/rendering/object.dart]

void _updateCompositingBits() {
if (!_needsCompositingBitsUpdate)
return;
final bool oldNeedsCompositing
= _needsCompositing;
_needsCompositing = false;
visitChildren((RenderObject child) {
//±éÀúËùÓÐ×ÓÏîÀ´¸üÐÂλºÏ³É
child._updateCompositingBits();
if (child.needsCompositing)
_needsCompositing = true;
});
if (isRepaintBoundary ||
alwaysNeedsCompositing)
_needsCompositing = true;
if (oldNeedsCompositing !=
_needsCompositing)
markNeedsPaint();
_needsCompositingBitsUpdate = false;
}

4.9 PipelineOwner.flushPaint

[-> lib/src/rendering/object.dart]

void flushPaint() {
profile(() { Timeline.startSync
('Paint', arguments:
timelineWhitelistArguments); });
try {
final List<RenderObject>
dirtyNodes = _nodesNeedingPaint;
_nodesNeedingPaint = <RenderObject>[];
//ÅÅÐòÔà½Úµã£¬Éî¶È×î´óµÄ½ÚµãÅŵÚһλ
for (RenderObject node in dirtyNodes..
sort((RenderObject a, RenderObject b)
=> b.depth - a.depth)) {
if (node._needsPaint &&
node.owner == this) {
//´Ë½ÚµãÊÇ·ñÁ¬½Óµ½Ê÷ÖУ¬
Èç¹ûÁ¬½ÓÔòÖØ»æ£¬·ñÔòÌø¹ý
if (node._layer.attached) {
PaintingContext.repaintCompositedChild
(node);
//[С½Ú4.9.1]
} else {
node._skippedPaintingOnLayer();
}
}
}
} finally {
profile(() { Timeline.finishSync(); });
}
}

4.9.1 repaintCompositedChild

[-> lib/src/rendering/object.dart]

static void repaintCompositedChild
(RenderObject child,
{ bool debugAlsoPaintedParent
= false }){
_repaintCompositedChild(
child,
debugAlsoPaintedParent:
debugAlsoPaintedParent,
);
}
static void _repaintCompositedChild(
RenderObject child, {
bool debugAlsoPaintedParent = false,
PaintingContext childContext,
}) {
if (child._layer == null) {
child._layer = OffsetLayer();
} else {
child._layer.removeAllChildren();
}
childContext ??= PaintingContext
(child._layer, child.paintBounds);
child._paintWithContext
(childContext, Offset.zero);
childContext.stopRecordingIfNeeded();
}

4.10 RenderView.compositeFrame

[-> lib/src/rendering/view.dart]

void compositeFrame() {
Timeline.startSync
('Compositing', arguments:
timelineWhitelistArguments);
try {
//´´½¨SceneBuilder [¼ûС½Ú4.10.1]
final ui.SceneBuilder builder
= ui.SceneBuilder();
//´´½¨Scene [¼ûС½Ú4.10.2]
final ui.Scene scene = layer.
buildScene(builder);
if (automaticSystemUiAdjustment)
_updateSystemChrome();
ui.window.render(scene);
// [¼ûС½Ú4.10.3]
scene.dispose();
} finally {
Timeline.finishSync();
}
}

¸Ã·½·¨Ö÷Òª¹¤×÷£º

·Ö±ð´´½¨Flutter¿ò¼Ü(dart)ºÍÒýÇæ²ã(C++)µÄÁ½¸öSceneBuilder£»

·Ö±ð´´½¨Flutter¿ò¼Ü(dart)ºÍÒýÇæ²ã(C++)µÄÁ½¸öScene£»

Ö´ÐÐrender()½«layerÊ÷·¢Ë͸øGPUỊ̈߳»

4.10.1 SceneBuilder³õʼ»¯

[-> lib/ui/compositing.dart]

class SceneBuilder extends
NativeFieldWrapperClass2 {
@pragma('vm:entry-point')
SceneBuilder() { _constructor(); }
void _constructor() native
'SceneBuilder_constructor';
...
}

SceneBuilder_constructorÕâÊÇnative·½·¨£¬×îÖÕµ÷Óõ½ÒýÇæÖеÄlib/ui/compositing/scene_builder.hÖеÄSceneBuilder::create()·½·¨£¬ ´´½¨C++µÄSceneBuilder¶ÔÏó¡£

4.10.2 OffsetLayer.buildScene

[-> lib/src/rendering/layer.dart]

ui.Scene buildScene
(ui.SceneBuilder builder) {
updateSubtreeNeedsAddToScene();
//±éÀúlayerÊ÷£¬½«ÐèÒª×ÓÊ÷¼ÓÈëµ½scene
addToScene(builder);
//½«layerÌí¼Óµ½SceneBuilder
return builder.build();
//µ÷ÓÃC++²ãµÄbuildÀ´¹¹½¨Scene¶ÔÏó¡£
}

±éÀúlayerÊ÷£¬½«ÐèÒª¸üеÄÈ«²¿¶¼¼ÓÈëµ½SceneBuilder¡£ÔÙµ÷ÓÃbuild()£¬Í¬ÑùÒ²ÊÇnative·½·¨£¬Ö´ÐÐSceneBuilder::build()À´¹¹½¨Scene¶ÔÏó¡£

4.10.3 Window::Render

[-> flutter/lib/ui/window/window.cc]

void Render(Dart_NativeArguments args){
Dart_Handle exception = nullptr;
Scene* scene = tonic::DartConverter
<Scene*>
::FromArguments(args, 1, exception);
if (exception) {
Dart_ThrowException(exception);
return;
}
UIDartState::Current()->window()
->client()->Render(scene); // [4.10.4]
}

ui.window.render()λÓÚwindow.dartÎļþ£¬ÕâÊÇÒ»¸önative·½·¨£¬»áµ÷Óõ½window.ccµÄRender()·½·¨¡£

4.10.4 RuntimeController::Render

[-> flutter/runtime/runtime_controller.cc]

void RuntimeController
::Render(Scene* scene) {
//´ÓsceneÖÐÈ¡³ölayerÊ÷
[¼ûС½Ú4.10.5]
client_.Render
(scene->takeLayerTree());
}

4.10.5 Engine::Render

[-> flutter/shell/common/engine.cc]

void Engine::Render
(std::unique_ptr<flow::
LayerTree> layer_tree) {
if (!layer_tree)
return;
SkISize frame_size = SkISize::Make
(viewport_metrics_.physical_width,
viewport_metrics_.physical_height);
if (frame_size.isEmpty())
return;
layer_tree->set_frame_size(frame_size);
animator_->Render(std::move(layer_tree));
// [4.10.6]
}

4.10.6 Animator::Render

[-> flutter/shell/common/animator.cc]

void Animator::Render
(std::unique_ptr<flow::LayerTree>
layer_tree) {
if (dimension_change_pending_ &&
layer_tree->frame_size() !=
last_layer_tree_size_) {
dimension_change_pending_ = false;
}
last_layer_tree_size_ =
layer_tree->frame_size();
if (layer_tree) {
layer_tree->set_construction_time
(fml::TimePoint::Now() -
last_begin_frame_time_);
}
//Ìá½»´ý´¦ÀíµÄcontinuation£¬
±¾´ÎPipelineProduceÍê³É
//[¼ûС½Ú4.10.7]
producer_continuation_.Complete
(std::move(layer_tree));
delegate_.OnAnimatorDraw
(layer_tree_pipeline_);
//[¼ûС½Ú4.10.8]
}

UIÏ̵߳ĺÄʱ´ÓdoFrame(frameTimeNanos)ÖеÄframeTimeNanosΪÆðµã£¬ÒÔAnimator::Render()·½·¨½áÊøÎªÖյ㣬 ²¢½«½á¹û±£´æµ½LayerTreeµÄ³ÉÔ±±äÁ¿construction_time_£¬Õâ±ãÊÇUIÏ̵߳ĺÄʱʱ³¤¡£

4.10.7 ProducerContinuation.Complete

[-> flutter/synchronization/pipeline.h]

class ProducerContinuation {
void Complete(ResourcePtr resource){
if (continuation_) {
continuation_(std::move(resource),
trace_id_);
continuation_ = nullptr;
TRACE_EVENT_ASYNC_END0
("flutter", "PipelineProduce",
trace_id_);
TRACE_FLOW_STEP("flutter",
"PipelineItem", trace_id_);
}
}

4.10.8 Shell::OnAnimatorDraw

[-> flutter/shell/common/shell.cc]

void Shell::OnAnimatorDraw(
fml::RefPtr<flutter::Pipeline
<flow::LayerTree>> pipeline) {
//ÏòGPUÏß³ÌÌá½»»æÖÆÈÎÎñ
task_runners_.GetGPUTaskRunner()->PostTask(
[rasterizer = rasterizer_->GetWeakPtr(),
pipeline = std::move(pipeline)]() {
if (rasterizer) {
//ÓÉGPUÏß³ÌÀ´¸ºÔðÕ¤¸ñ»¯²Ù×÷
rasterizer->Draw(pipeline);
}
});
}

Õâ¸ö·½·¨Ö÷ÒªÊÇÏòGPUÏß³ÌÌá½»»æÖÆÈÎÎñ¡£

4.11 PipelineOwner.flushSemantics

[-> lib/src/rendering/view.dart]

void flushSemantics() {
if (_semanticsOwner == null)
return;
profile(() { Timeline.startSync
('Semantics'); });
try {
final List<RenderObject>
nodesToProcess =
_nodesNeedingSemantics.toList()
..sort((RenderObject a,
RenderObject b) => a.depth - b.depth);
_nodesNeedingSemantics.clear();
//±éÀú_nodesNeedingSemantics£¬
¸üÐÂÐèÒª¸üÐÂÓïÒåµÄäÖȾ¶ÔÏó
for (RenderObject node in
nodesToProcess) {
if (node._needsSemanticsUpdate
&& node.owner == this)
node._updateSemantics();
// [¼ûС½Ú4.11.1]
}
_semanticsOwner.sendSemanticsUpdate();
// ·¢ËÍÓïÒå¸üÐÂ[¼ûС½Ú4.11.2]
} finally {
profile(() { Timeline.finishSync(); });
}
}

4.11.1 _updateSemantics

[-> lib/src/rendering/object.dart]

void _updateSemantics() {
if (_needsLayout) {
//´Ë×ÓÊ÷ÖÐûÓÐ×ã¹»µÄÐÅÏ¢À´¼ÆËãÓïÒ壬
×ÓÊ÷¿ÉÄܱ»ÊÓͼ´°¿Ú±£³Ö»î×ŵ«Ã»Óв¼¾Ö
return;
}
final _SemanticsFragment fragment
= _getSemanticsForParent(
mergeIntoParent: _semantics?.
parent?.isPartOfNodeMerging ?? false,
);
final _InterestingSemanticsFragment
interestingFragment = fragment;
final SemanticsNode node = interestingFragment.compileChildren(
parentSemanticsClipRect: _semantics?.parentSemanticsClipRect,
parentPaintClipRect: _semantics?.
parentPaintClipRect,
).single;
}

4.11.2 sendSemanticsUpdate

[-> lib/src/semantics/semantics.dart]

void sendSemanticsUpdate() {
if (_dirtyNodes.isEmpty)
return;
final Set<int>
customSemanticsActionIds = Set<int>();
final List<SemanticsNode> visitedNodes = <SemanticsNode>[];
while (_dirtyNodes.isNotEmpty) {
final List<SemanticsNode>
localDirtyNodes = _dirtyNodes.
where((SemanticsNode node) => !_detachedNodes.contains(node)).toList();
_dirtyNodes.clear();
_detachedNodes.clear();
localDirtyNodes.sort
((SemanticsNode a, SemanticsNode b)
=> a.depth - b.depth);
visitedNodes.addAll(localDirtyNodes);
for (SemanticsNode node in
localDirtyNodes) {
if (node.isPartOfNodeMerging) {
//Èç¹ûºÏ²¢µ½¸¸½Úµã£¬È·±£¸¸½ÚµãÒѱ»Ìí¼Óµ½ÔàÁбí
if (node.parent != null && node.parent.isPartOfNodeMerging)
node.parent._markDirty(); //½«½ÚµãÌí¼Óµ½ÔàÁбí
}
}
}
visitedNodes.sort((SemanticsNode a,
SemanticsNode b) => a.depth - b.depth);
final ui.SemanticsUpdateBuilder builder = ui.SemanticsUpdateBuilder();
for (SemanticsNode node in visitedNodes) {
if (node._dirty && node.attached)
node._addToUpdate(builder,
customSemanticsActionIds);
}
_dirtyNodes.clear();
for (int actionId in
customSemanticsActionIds) {
final CustomSemanticsAction action = CustomSemanticsAction.getAction(actionId);
builder.updateCustomAction(id: actionId, label: action.label, hint: action.hint, overrideId: action.action?.index ?? -1);
}
ui.window.updateSemantics(builder.build());
// [¼ûС½Ú4.11.3]
notifyListeners(); //֪ͨÒÑ×¢²áµÄ¼àÌýÆ÷
}

¿ÉÒÔ¿´¿´¼àÌýÆ÷µÄÊý¾Ý£¬ÊÇ·ñÓ°ÏìÐÔÄÜ¡£

updateSemanticsÕâÊÇwindow.dartÖеÄÒ»¸önative·½·¨£¬µ÷Óõ½ÈçÏ·½·¨¡£

4.11.3 Window::updateSemantics

[-> flutter/lib/ui/window/window.cc]
void UpdateSemantics
(Dart_NativeArguments args) {
Dart_Handle exception = nullptr;
SemanticsUpdate* update =
tonic::DartConverter<SemanticsUpdate*>
::FromArguments(args, 1, exception);
if (exception) {
Dart_ThrowException(exception);
return;
}
UIDartState::Current()->window()
->client()->UpdateSemantics(update);
// [¼ûС½Ú4.11.4]
}

4.11.4 RuntimeController::UpdateSemantics

[-> flutter/runtime/runtime_controller.cc]

void RuntimeController::
UpdateSemantics(SemanticsUpdate* update){
if (window_data_.semantics_enabled) {
client_.UpdateSemantics
(update->takeNodes(),
update->takeActions());
// [¼ûС½Ú4.11.5]
}
}

4.11.5 Engine::UpdateSemantics

[-> flutter/shell/common/engine.cc]

void Engine::UpdateSemantics
(blink::SemanticsNodeUpdates update,
blink::CustomAccessibility
ActionUpdates actions) {
delegate_.OnEngineUpdateSemantics
(std::move(update), std::move(actions));
// [¼ûС½Ú4.11.6]
}

4.11.6 Shell::OnAnimatorDraw

[-> flutter/shell/common/shell.cc]

void Shell::OnEngineUpdateSemantics(
blink::SemanticsNodeUpdates update,
blink::CustomAccessibilityActionUpdates
actions) {
task_runners_.GetPlatformTaskRunner()
->PostTask(
[view = platform_view_->GetWeakPtr(),
update = std::move(update),
actions = std::move(actions)] {
if (view) {
view->UpdateSemantics(std::move(update), std::move(actions));
}
});
}

Õâ¸ö·½·¨Ö÷ÒªÊÇÏòƽ̨Ïß³ÌÌá½»SemanticÈÎÎñ¡£

Ôٻص½Ð¡½Ú4.6£¬¿ÉÖª½ÓÏÂÀ´ÔÙÖ´ÐÐfinalizeTree()²Ù×÷£»

4.12 BuildOwner.finalizeTree

[-> lib/src/widgets/framework.dart]

void finalizeTree() {
Timeline.startSync('Finalize tree',
arguments: timelineWhitelistArguments);
try {
lockState(() {
//±éÀúËùÓеÄElement£¬Ö´ÐÐunmount()¶¯×÷£¬
ÇÒÈ¡ÏûGlobalKeysµÄ×¢²á
_inactiveElements._unmountAll();
});
} catch (e, stack) {
_debugReportException('while
finalizing the widget tree', e, stack);
} finally {
Timeline.finishSync();
}
}

±éÀúËùÓеÄElement£¬Ö´ÐÐÏàÓ¦¾ßÌåElement×ÓÀàµÄunmount()²Ù×÷£¬ÏÂÃæÒÔ³£¼ûµÄStatefulElementΪÀýÀ´ËµÃ÷¡£

4.12.1 StatefulElement.unmount

[-> lib/src/widgets/framework.dart]

void unmount() {
super.unmount(); //[¼ûС½Ú4.12.2]
_state.dispose();
//Ö´ÐÐStateµÄdispose()·½·¨
_state._element = null;
_state = null;
}

4.12.2 Element.unmount

[-> lib/src/widgets/framework.dart]

void unmount() {
if (widget.key is GlobalKey) {
final GlobalKey key = widget.key;
key._unregister(this);
//È¡ÏûGlobalKeyµÄ×¢²á
}
}

¸½Â¼

±¾ÎÄÉæ¼°µ½Ïà¹ØÔ´ÂëÎļþ

flutter/shell/common/
- vsync_waiter.cc
- engine.cc
- animator.cc
- shell.cc
- rasterizer.cc
flutter/shell/platform/android/
- vsync_waiter_android.cc
- platform_view_android_jni.cc
- library_loader.cc
- io/flutter/view/VsyncWaiter.java
flutter/runtime/runtime_controller.cc
flutter/synchronization/pipeline.h
flutter/fml/message_loop_impl.cc
flutter/lib/ui/window/window.cc
flutter/lib/ui/window.dart
flutter/lib/ui/hooks.dart
lib/src/widgets/framework.dart
lib/src/widgets/binding.dart
lib/src/scheduler/binding.dart
lib/src/semantics/semantics.dart
lib/src/rendering/
- binding.dart
- object.dart
- view.dart
 
   
2359 ´Îä¯ÀÀ       27
Ïà¹ØÎÄÕÂ

Éî¶È½âÎö£ºÇåÀíÀôúÂë
ÈçºÎ±àд³öÓµ±§±ä»¯µÄ´úÂë
ÖØ¹¹-ʹ´úÂë¸ü¼ò½àÓÅÃÀ
ÍŶÓÏîÄ¿¿ª·¢"±àÂë¹æ·¶"ϵÁÐÎÄÕÂ
Ïà¹ØÎĵµ

ÖØ¹¹-¸ÄÉÆ¼ÈÓдúÂëµÄÉè¼Æ
Èí¼þÖØ¹¹v2
´úÂëÕû½àÖ®µÀ
¸ßÖÊÁ¿±à³Ì¹æ·¶
Ïà¹Ø¿Î³Ì

»ùÓÚHTML5¿Í»§¶Ë¡¢Web¶ËµÄÓ¦Óÿª·¢
HTML 5+CSS ¿ª·¢
ǶÈëʽC¸ßÖÊÁ¿±à³Ì
C++¸ß¼¶±à³Ì