4startup_dart_framework

类设计

runApp

main.dart

void main() => runApp(MyApp());

widgets/binding.dart

void runApp(Widget app) {
  WidgetsFlutterBinding.ensureInitialized()
   ..attachRootWidget(app)
   ..scheduleWarmUpFrame();
 }

WidgetsFlutterBinding.ensureInitialized()

/// A concrete binding for applications based on the Widgets framework.
/// This is the glue that binds the framework to the Flutter engine.

class WidgetsFlutterBinding extends BindingBase with GestureBinding, ServicesBinding, SchedulerBinding, PaintingBinding, SemanticsBinding, RendererBinding, WidgetsBinding {
  /// Returns an instance of the [WidgetsBinding], creating and
  /// initializing it if necessary. If one is created, it will be a
  /// [WidgetsFlutterBinding]. If one was previously initialized, then
  /// it will at least implement [WidgetsBinding].
  ///
  /// You only need to call this method if you need the binding to be
  /// initialized before calling [runApp].
  ///
  /// In the `flutter_test` framework, [testWidgets] initializes the
  /// binding instance to a [TestWidgetsFlutterBinding], not a
  /// [WidgetsFlutterBinding].
  static WidgetsBinding ensureInitialized() {
   if (WidgetsBinding.instance == null)
    WidgetsFlutterBinding();
   return WidgetsBinding.instance;
  }
 }
/// Default abstract constructor for bindings.
 ///
 /// First calls [initInstances] to have bindings initialize their
 /// instance pointers and other state, then calls
 /// [initServiceExtensions] to have bindings initialize their
 /// observatory service extensions, if any.
 BindingBase() {
  initInstances();
  initServiceExtensions();
 }

SchedulerBinding.initInstances

@override
 void initInstances() {
  super.initInstances();
  _instance = this;
  window.onBeginFrame = _handleBeginFrame;
  window.onDrawFrame = _handleDrawFrame;
ensureVisualUpdate
void ensureVisualUpdate() {
  switch (schedulerPhase) {
   case SchedulerPhase.idle:
   case SchedulerPhase.postFrameCallbacks:
    scheduleFrame();
    return;
   case SchedulerPhase.transientCallbacks:
   case SchedulerPhase.midFrameMicrotasks:
   case SchedulerPhase.persistentCallbacks:
    return;
  }}

RendererBinding.initInstances

PipelineOwner()
@override
 void initInstances() {
  super.initInstances();

_instance = this;
 _pipelineOwner = PipelineOwner(
  onNeedVisualUpdate: ensureVisualUpdate,
  onSemanticsOwnerCreated: _handleSemanticsOwnerCreated,
  onSemanticsOwnerDisposed: _handleSemanticsOwnerDisposed,
 );

initRenderView();
addPersistentFrameCallback(_handlePersistentFrameCallback);
initRenderView
/// Creates a [RenderView] object to be the root of the
 /// [RenderObject] rendering tree, and initializes it so that it
 /// will be rendered when the engine is next ready to display a
 /// frame.
 ///
 /// Called automatically when the binding is created.
 void initRenderView() {
  assert(renderView == null);
  renderView = RenderView(configuration: createViewConfiguration(), window: window);
  renderView.scheduleInitialFrame();
 }
/// Bootstrap the rendering pipeline by scheduling the first frame.
 ///
 /// This should only be called once, and must be called before changing
 /// [configuration]. It is typically called immediately after calling the
 /// constructor.
 void scheduleInitialFrame() {
 scheduleInitialLayout();
 scheduleInitialPaint(_updateMatricesAndCreateNewRootLayer());//配置TransformLayer
 owner.requestVisualUpdate();
 }
_handlePersistentFrameCallback
void _handlePersistentFrameCallback(Duration timeStamp) {
   drawFrame();
 }
drawFrame
/// Pump the rendering pipeline to generate a frame.
 ///
 /// This method is called by [handleDrawFrame], which itself is called
 /// automatically by the engine when it is time to lay out and paint a frame.
 ///
 /// Each frame consists of the following phases:
/// 1. The animation phase
/// 2. Microtasks
/// 3. The layout phase
/// 4. The compositing bits phase
/// 5. The paint phase
/// 6. The compositing phase
/// 7. The semantics phase
/// 8. The finalization phase

@protected
 void drawFrame() {
  assert(renderView != null);
  pipelineOwner.flushLayout();
  pipelineOwner.flushCompositingBits();
  pipelineOwner.flushPaint();
  renderView.compositeFrame(); // this sends the bits to the GPU
  pipelineOwner.flushSemantics(); // this also sends the semantics to the OS.
 }

WidgetsBinding.initInstances

@override
 void initInstances() {
  super.initInstances();
  _instance = this;
  buildOwner.onBuildScheduled = _handleBuildScheduled;
drawFrame
/// Pump the build and rendering pipeline to generate a frame.
 ///
 /// This method is called by [handleDrawFrame], which itself is called
 /// automatically by the engine when when it is time to lay out and paint a
 /// frame.
@override
 void drawFrame() {
   if (renderViewElement != null)
     buildOwner.buildScope(renderViewElement);
   super.drawFrame();
 }
_handleBuildScheduled
void _handleBuildScheduled() {
ensureVisualUpdate();}

attachRootWidget

/// The glue between the widgets layer and the Flutter engine.
 mixin WidgetsBinding on BindingBase, SchedulerBinding, GestureBinding, RendererBinding, SemanticsBinding {
   
/// Takes a widget and attaches it to the [renderViewElement], creating it if
 /// necessary.
 ///
 /// This is called by [runApp] to configure the widget tree.
 ///
 /// See also [RenderObjectToWidgetAdapter.attachToRenderTree].
 void attachRootWidget(Widget rootWidget) {
  _renderViewElement = RenderObjectToWidgetAdapter<RenderBox>(
   container: renderView,
   debugShortDescription: '[root]',
   child: rootWidget,
  ).attachToRenderTree(buildOwner, renderViewElement);
 }
/// A bridge from a [RenderObject] to an [Element] tree.
class RenderObjectToWidgetAdapter<T extends RenderObject> extends RenderObjectWidget {
  /// Inflate this widget and actually set the resulting [RenderObject] as the
 /// child of [container].
 ///
 /// If `element` is null, this function will create a new element. Otherwise,
 /// the given element will have an update scheduled to switch to this widget.
 ///
 /// Used by [runApp] to bootstrap applications.
 RenderObjectToWidgetElement<T> attachToRenderTree(BuildOwner owner, [ RenderObjectToWidgetElement<T> element ]) {
  if (element == null) {
   owner.lockState(() {
    element = createElement();
    assert(element != null);
    element.assignOwner(owner);
   });
   owner.buildScope(element, () {//main
    element.mount(null, null);
   });
  } else {
   element._newWidget = this;
   element.markNeedsBuild();
  }
  return element;
 }
}

参考渲染/widget/buildscope

mixin SchedulerBinding

scheduleWarmUpFrame

void scheduleWarmUpFrame() {
  handleBeginFrame(null);
  handleDrawFrame();
  if (hadScheduledFrame)
    scheduleFrame();
}

handleBeginFrame

void handleBeginFrame(Duration rawTimeStamp) {
assert(schedulerPhase == SchedulerPhase.idle);
 _hasScheduledFrame = false;
 try {
  // TRANSIENT FRAME CALLBACKS
  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;
 }

handleDrawFrame

/// Called by the engine to produce a new frame.
void handleDrawFrame() {//将会调用drawFrame
// PERSISTENT FRAME CALLBACKS
 _schedulerPhase = SchedulerPhase.persistentCallbacks;
 for (FrameCallback callback in _persistentCallbacks)
  _invokeFrameCallback(callback, _currentFrameTimeStamp);
 
 // POST-FRAME CALLBACKS
 _schedulerPhase = SchedulerPhase.postFrameCallbacks;
 final List<FrameCallback> localPostFrameCallbacks =
   List<FrameCallback>.from(_postFrameCallbacks);
 _postFrameCallbacks.clear();
 for (FrameCallback callback in localPostFrameCallbacks)
  _invokeFrameCallback(callback, _currentFrameTimeStamp);
void _invokeFrameCallback(FrameCallback callback, Duration timeStamp, [ StackTrace callbackStack ]) {
  callback(timeStamp);
/// If necessary, schedules a new frame by calling [Window.scheduleFrame].
void scheduleFrame() {
  if (_hasScheduledFrame || !_framesEnabled)
   return;
  ensureFrameCallbacksRegistered();
  window.scheduleFrame();
  _hasScheduledFrame = true;
}

  /// Ensures callbacks for `window.onBeginFrame` and `window.onDrawFrame` are registered.
  @protected
  void ensureFrameCallbacksRegistered() {
    window.onBeginFrame ??= _handleBeginFrame;
    window.onDrawFrame ??= _handleDrawFrame;
  }

其他

Window

/// The most basic interface to the host operating system’s user interface.

scheduleFrame

/// Requests that, at the next appropriate opportunity, the [onBeginFrame]
 /// and [onDrawFrame] callbacks be invoked.
 void scheduleFrame() native 'Window_scheduleFrame';
/// A callback that is invoked to notify the application that it is an
 /// appropriate time to provide a scene using the [SceneBuilder] API and the
 /// [render] method. When possible, this is driven by the hardware VSync
 /// signal. This is only called if [scheduleFrame] has been called since the
 /// last time this callback was invoked.



/// The [onDrawFrame] callback is invoked immediately after [onBeginFrame],
 /// after draining any microtasks (e.g. completions of any [Future]s) queued
 /// by the [onBeginFrame] handler.

FrameCallback get onBeginFrame => _onBeginFrame;
 set onBeginFrame(FrameCallback callback) {
  _onBeginFrame = callback;
   
 VoidCallback get onDrawFrame => _onDrawFrame;
 set onDrawFrame(VoidCallback callback) {

render

/// Updates the application's rendering on the GPU with the newly provided
 /// [Scene]. This function must be called within the scope of the
 /// [onBeginFrame] or [onDrawFrame] callbacks being invoked.

/// To record graphical operations, first create a [PictureRecorder], then
 /// construct a [Canvas], passing that [PictureRecorder] to its constructor.
 /// After issuing all the graphical operations, call the
 /// [PictureRecorder.endRecording] function on the [PictureRecorder] to obtain
 /// the final [Picture] that represents the issued graphical operations.

///
 /// Next, create a [SceneBuilder], and add the [Picture] to it using
 /// [SceneBuilder.addPicture]. With the [SceneBuilder.build] method you can
 /// then obtain a [Scene] object, which you can display to the user via this
 /// [render] function.

void render(Scene scene) native 'Window_render';

PipelineOwner

/// The pipeline owner manages the rendering pipeline.

/// The [RendererBinding] holds the pipeline owner for the render objects that
 /// are visible on screen. You can create other pipeline owners to manage
 /// off-screen objects, which can flush their pipelines independently of the
 /// on-screen render objects.

PipelineOwner
  
/// The unique object managed by this pipeline that has no parent.
 ///
 /// This object does not have to be a [RenderObject].
 AbstractNode get rootNode => _rootNode;
 AbstractNode _rootNode;

List<RenderObject> _nodesNeedingLayout = <RenderObject>[];
List<RenderObject> _nodesNeedingPaint = <RenderObject>[];
final List<RenderObject> _nodesNeedingCompositingBitsUpdate = <RenderObject>[];

final VoidCallback onNeedVisualUpdate;

requestVisualUpdate

/// Used to notify the pipeline owner that an associated render object wishes
 /// to update its visual appearance.
 void requestVisualUpdate() {
  if (onNeedVisualUpdate != null)
   onNeedVisualUpdate();
 }

flushLayout

/// Update the layout information for all dirty render objects.

void flushLayout() {
while (_nodesNeedingLayout.isNotEmpty) {
  final List<RenderObject> dirtyNodes = _nodesNeedingLayout;
  _nodesNeedingLayout = <RenderObject>[];
  for (RenderObject node in dirtyNodes..sort((RenderObject a, RenderObject b) => a.depth - b.depth)) {
   if (node._needsLayout && node.owner == this)
    node._layoutWithoutResize();
  }

flushCompositingBits

/// Updates the [RenderObject.needsCompositing] bits.

void flushCompositingBits() {
_nodesNeedingCompositingBitsUpdate.sort((RenderObject a, RenderObject b) => a.depth - b.depth);
 for (RenderObject node in _nodesNeedingCompositingBitsUpdate) {
  if (node._needsCompositingBitsUpdate && node.owner == this)
   node._updateCompositingBits();
 }
 _nodesNeedingCompositingBitsUpdate.clear();

flushPaint

/// Update the display lists for all render objects.
 ///
 /// This function is one of the core stages of the rendering pipeline.
 /// Painting occurs after layout and before the scene is recomposited so that
 /// scene is composited with up-to-date display lists for every render object.
 ///
 /// See [RendererBinding] for an example of how this function is used.
 void flushPaint() {
final List<RenderObject> dirtyNodes = _nodesNeedingPaint;
 _nodesNeedingPaint = <RenderObject>[];
 // Sort the dirty nodes in reverse order (deepest first).
 for (RenderObject node in dirtyNodes..sort((RenderObject a, RenderObject b) => b.depth - a.depth)) {
  assert(node._layer != null);
  if (node._needsPaint && node.owner == this) {
   if (node._layer.attached) {
    PaintingContext.repaintCompositedChild(node);//main
   } else {
    node._skippedPaintingOnLayer();
   }
  }

RenderObjectToWidgetAdapter

/// A bridge from a [RenderObject] to an [Element] tree.
class RenderObjectToWidgetAdapter<T extends RenderObject> extends RenderObjectWidget 

/// The widget below this widget in the tree.
 ///
 /// {@macro flutter.widgets.child}
 final Widget child;

/// The [RenderObject] that is the parent of the [Element] created by this widget.
 final RenderObjectWithChildMixin<T> container;

@override
 RenderObjectToWidgetElement<T> createElement() => RenderObjectToWidgetElement<T>(this);

 @override
 RenderObjectWithChildMixin<T> createRenderObject(BuildContext context) => container;

RenderObjectToWidgetElement<T> attachToRenderTree(BuildOwner owner, [ RenderObjectToWidgetElement<T> element ]) {}

RootRenderObjectElement

/// The element at the root of the tree.
 ///
 /// Only root elements may have their owner set explicitly. All other
 /// elements inherit their owner from their parent.

 RootRenderObjectElement extends RenderObjectElement 

mount

@override
 void mount(Element parent, dynamic newSlot) {
  // Root elements should never have parents.
  assert(parent == null);
  assert(newSlot == null);
  super.mount(parent, newSlot);
 }

RenderObjectToWidgetElement

RenderObjectToWidgetElement<T extends RenderObject> {
Element _child;

@override
 RenderObjectWithChildMixin<T> get renderObject => super.renderObject;
}

mount

@override
 void mount(Element parent, dynamic newSlot) {
  assert(parent == null);
  super.mount(parent, newSlot);//1将自己挂在父节点上
 _rebuild();//2:通过调用updateChild逐个将child挂在自己上
}

update

 @override
 void update(RenderObjectToWidgetAdapter<T> newWidget) {
  super.update(newWidget);
  assert(widget == newWidget);
  _rebuild();
 }

_rebuild

void _rebuild() {
   _child = updateChild(_child, widget.child, _rootChildSlot);

insertChildRenderObject

@override
 void insertChildRenderObject(RenderObject child, dynamic slot) {
  renderObject.child = child;
 }