当前位置: 首页 > news >正文

溧阳网站建设哪家好经典重庆论坛

溧阳网站建设哪家好,经典重庆论坛,vps做网站教程,上门做指甲哪个网站一#xff0c;Mixins1#xff0c;定义#xff1a;Mixins 是一种在多个类层次结构中重用类代码的方法。个人理解#xff1a;就是一个类#xff0c;这个类有一些方法#xff0c;其他类可以在不继承这个类的情况下使用这个类的方法。2#xff0c;几个关键词#xff08;1Mixins1定义Mixins 是一种在多个类层次结构中重用类代码的方法。个人理解就是一个类这个类有一些方法其他类可以在不继承这个类的情况下使用这个类的方法。2几个关键词1mixin:一般使用mixin关键字定义可以混合的类2with:使用混合时用with关键字1on:添加限定条件如下意思是这个类只能被on的类或者子类混合3现在有这个情况class A{A(){print(A constructor);}log() print(A log); } mixin AA on A{log() {print(AA log);} } mixin AB on A{overridelog() {super.log();print(AB log);} } //C是A的子类所以可以混合AA和AB class C extends A with AA,AB{overridelog() {super.log();print(C log);} }类C继承类A并且混合了AA和AB这几个类都有log方法现在执行C().log()会输出什么答案是I/flutter (16574): A constructor I/flutter (16574): AA log I/flutter (16574): AB log I/flutter (16574): C log因为混合类时进行混合的多个类是线性的所以他们的共有方法不会冲突会优先调用后面混合的类的方法所以混合的顺序决定了混合时相同的方法的处理逻辑。像这个例子执行的方法肯定是C.log但因为super.log()所以会调用AB.log,AA.log,因为AA.log没有super,所以没有调用A.log。mixin的类不能有构造函数,不能继承其他类因为mixin机制语义上是向一个类混入其他类的方法或者成员变量,使得我们可以在混合类中访问到混入类的方法或者属性。而混入其他类的构造函数实际上是没有意义的,因为不会有人手动去调用这个混入类的构造函数。二runAPP()从这儿开始执行runApp(const MyApp());void runApp(Widget app) {//1,初始化//2绑定根节点//3绘制热身帧WidgetsFlutterBinding.ensureInitialized()..scheduleAttachRootWidget(app)..scheduleWarmUpFrame(); }2.1初始化2.1.1初始化函数看下初始化函数这儿是WidgetsFlutterBinding的单例过程因为要确保flutter完成初始化并且只完成一次这儿调用了自己的构造器static WidgetsBinding ensureInitialized() {if (WidgetsBinding._instance null)WidgetsFlutterBinding();return WidgetsBinding.instance; }对于WidgetsFlutterBinding这个类继承了BindingBase并且混入了7个类class WidgetsFlutterBinding extends BindingBase with GestureBinding, SchedulerBinding, ServicesBinding, PaintingBinding, SemanticsBinding, RendererBinding, WidgetsBinding{因为WidgetsFlutterBinding继承BindingBase在调用构造方法前会先调用BindingBase的构造方法所以看下父类BindingBase的构造方法BindingBase() {developer.Timeline.startSync(Framework initialization);//注意这个方法其他七个混入的类都有//绑定初始化initInstances();//在绑定初始化完成后进行服务初始化initServiceExtensions();developer.postEvent(Flutter.FrameworkInitialization, String, String{});developer.Timeline.finishSync(); }因为initInstances()方法其他几个混入的类都有所以WidgetsBinding 会覆盖前面混入的 initInstances()所以 WidgetsBinding 的 initInstances() 会首先被调用而 WidgetsBinding 还有其他几个混入的类的 initInstances 函数中都执行了super.initInstances();所以根据mixin的特性 initInstances 的执行顺序依次是BindingBase - GestureBinding - SchedulerBinding - ServicesBinding - PaintingBinding - SemanticsBinding - RendererBinding - WidgetsBinding从而依次完成各个 Binding 的初始化相关工作。2.1.2七个Bindding1GestureBinding手势事件绑定主要处理触屏幕指针事件的分发以及事件最终回调处理。2SchedulerBinding绘制调度绑定,和绘制渲染流程有关。3ServicesBinding1platform与flutter层通信相关服务的初始化接收MethodChannel和SystemChannels传递过来的消息2注册监听了flutter app的生命周期变化事件根据生命周期状态决定是否允许发起绘制任务4PaintingBinding和图片缓存有关。5SemanticsBinding语义相关的初始化主要就是描述应用程序中的UI信息用于读屏使用。6RendererBinding1初始化了渲染管道PipelineOwner和RenderView这就是我们屏幕真实显示的那个ViewFlutter是单页面的UI框架renderView就是这个时间点被初始化出来的。2注意初始化方法中把renderView挂载到pipelineOwner.rootNode上RenderView是RenderObject的子类renderView其实是Render tree 的根节点后续会讲到。7WidgetsBinding1初始化了一个BuildOwner对象它主要是执行widget tree的build任务2执行了一些window的回调。2.2绑定根节点2.2.1接下来看绑定根节点的方法scheduleAttachRootWidget()void scheduleAttachRootWidget(Widget rootWidget) {Timer.run(() {//传入了rootWidget这个rootWidget就是我们构建的MyApp()这个方法主要是绑定根节点attachRootWidget(rootWidget);}); }/// 创建树的根节点 /// 这个方法主要是将根widget和根element和根renderObject关联起来 /// 并将唯一的BuildOwner对象引用作为根对象的持有对象通过继承关系层层传递 void attachRootWidget(Widget rootWidget) {final bool isBootstrapFrame renderViewElement null;_readyToProduceFrames true;//1初始化了一个RenderObjectToWidgetAdapter对象//RenderObjectToWidgetAdapter继承RenderObjectWidget所以本质是一个widget可以说创建了widget树的根节点//调用attachToRenderTree_renderViewElement RenderObjectToWidgetAdapterRenderBox(container: renderView,//之前介绍的在RendererBinding初始化的对象也是renderObject的根节点debugShortDescription: [root],child: rootWidget,//根widget就是runAPP传入的MyApp()).attachToRenderTree(buildOwner!, renderViewElement as RenderObjectToWidgetElementRenderBox?);if (isBootstrapFrame) {SchedulerBinding.instance.ensureVisualUpdate();} }RenderView get renderView _pipelineOwner.rootNode! as RenderView; /// 这儿创建了element树的根节点并返回了element /// 也就是_renderViewElement其实就是element树的根 RenderObjectToWidgetElementT attachToRenderTree(BuildOwner owner, [ RenderObjectToWidgetElementT? element ]) {if (element null) {owner.lockState(() {//创建element树的根节点 RenderObjectToWidgetElementelement createElement();assert(element ! null);//绑定BuildOwner通过 BuildOwner 构建需要构建的 elementelement!.assignOwner(owner);});//BuildOwner构建elementowner.buildScope(element!, () {element!.mount(null, null);});} else {element._newWidget this;element.markNeedsBuild();}return element!; }现在为止出现了三棵树的根widget树RenderObjectToWidgetAdapter对象element树RenderObjectToWidgetElement对象renderObject树RenderView对象。接下来看mount方法作用就是将element添加到树种的parent节点上。//1RenderObjectToWidgetElement override void mount(Element? parent, Object? newSlot) {assert(parent null);//先看下mount方法都做了什么super.mount(parent, newSlot);//在这儿触发了_rebuild方法该方法调用了updateChild方法_rebuild();assert(_child ! null); }//2, RenderObjectElement//创建了renderObjectoverridevoid mount(Element? parent, Object? newSlot) {super.mount(parent, newSlot);_renderObject (widget as RenderObjectWidget).createRenderObject(this);attachRenderObject(newSlot);_dirty false;}//因为widget是RenderObjectToWidgetAdapter类型其createRenderObject返回的了container//这个container就是我们之前传的renderViewRenderObjectWithChildMixinT createRenderObject(BuildContext context) container;//将renderObject挂载到RenderObject Tree上void attachRenderObject(Object? newSlot) {_slot newSlot;_ancestorRenderObjectElement _findAncestorRenderObjectElement();_ancestorRenderObjectElement?.insertRenderObjectChild(renderObject, newSlot);final ParentDataElementParentData? parentDataElement _findAncestorParentDataElement();if (parentDataElement ! null)_updateParentData(parentDataElement.widget as ParentDataWidgetParentData);}//3, Element//首先执行的mount主要是设置parentslot等的值void mount(Element? parent, Object? newSlot) {_parent parent;//element树上的父节点_slot newSlot;//子element在父节点上的位置_lifecycleState _ElementLifecycle.active;_depth _parent ! null ? _parent!.depth 1 : 1;//element树的深度if (parent ! null) {_owner parent.owner;}final Key? key widget.key;if (key is GlobalKey) {owner!._registerGlobalKey(key, this);}_updateInheritance();attachNotificationTree();}以上mount执行顺序为Element.mount-RenderObjectElement.mount-RenderObjectToWidgetElement.mount执行完毕后在Element.mount函数这里会触发_rebuild();在_rebuild()里面我们看到了Element.updateChild()。 void _rebuild() {try {//_child为null第二个入参就是MyApp()_child updateChild(_child, (widget as RenderObjectToWidgetAdapterT).child, _rootChildSlot);} catch (exception, stack) {...}}Element.updateChild()其实是element很重要的一个方法作为widget和renderobject的桥梁这个方法会根据不同的条件去创建、更新、删除element。这里可见就是build子widget这里就是build MyApp() //这里传的child是null Element? updateChild(Element? child, Widget? newWidget, Object? newSlot) {final Element newChild;if (child ! null) {//.......} else {newChild inflateWidget(newWidget, newSlot);}return newChild;}updateChild里有调用inflateWidget方法inflateWidget这个函数 Element inflateWidget(Widget newWidget, Object? newSlot) {...try {...//这儿就是为widget创建对应的element对象所以widget和element关联起来了final Element newChild newWidget.createElement();//又调用了mount方法将子element挂载到当前element结点上newChild.mount(this, newSlot);return newChild;} finally {...}}在这个函数里面就会触发 createElement去创建element ,element又会去调用对应类的mount函数。经过一系列的流程之后又会回到inflateWidget这个函数中再次触发新的mount函数形成一个层层调用不断创建parentElement到childElement的过程,这个过程完成了element tree的构建。2.2.2三棵树简介WIdget树存放渲染内容element树分离 WidgetTree 和真正的渲染对象的中间层 WidgetTree 用来描述对应的Element 属性,同时持有Widget和RenderObject存放上下文信息通过它来遍历视图树支撑UI结构。RenderObject树用于应用界面的布局和绘制负责真正的渲染保存了元素的大小布局等信息实例化一个 RenderObject 是非常耗能的。总结当应用启动时Flutter会遍历并创建所有的 Widget 形成 Widget Tree通过调用 Widget 上的 createElement() 方法创建每个 Element 对象形成 Element Tree。最后调用 Element 的 createRenderObject() 方法创建每个渲染对象形成一个 Render Tree。为什么要这样widget的重建开销非常小所以可以随意的重建因为它不一会导致页面重绘并且它也不一定会常常变化。 而renderObject如果频繁创建和销毁成本就很高了对性能的影响比较大因此它会缓存所有页面元素只是当这些元素有变化时才去重绘页面。而判断页面有无变化就依靠element了每次widget变化时element会比较前后两个widget只有当某一个位置的Widget和新Widget不一致才会重新创建Element和widget其他时候则只会修改renderObject的配置而不会进行耗费性能的RenderObject的实例化工作了。2.3绘制热身帧void scheduleWarmUpFrame() {if (_warmUpFrame || schedulerPhase ! SchedulerPhase.idle)return;_warmUpFrame true;final TimelineTask timelineTask TimelineTask()..start(Warm-up frame);final bool hadScheduledFrame _hasScheduledFrame;Timer.run(() {assert(_warmUpFrame);//1handleBeginFrame(null);});Timer.run(() {assert(_warmUpFrame);//2handleDrawFrame();resetEpoch();_warmUpFrame false;if (hadScheduledFrame)scheduleFrame();});lockEvents(() async {await endOfFrame;timelineTask.finish();}); }scheduleWarmUpFrame绘制的是根节点RenderObject对应的TransformLayer对象调用handleBeginFrame和handleDrawFrame方法通过pipelineOwner去执行layoutpaint等一些列操作。并且scheduleWarmUpFrame是立即去绘制的因为启动的显示要越快越好。后面的lockEvents也是为了等待预约帧绘制完成后再去执行其他的任务。
http://www.ho-use.cn/article/10820194.html

相关文章:

  • 网站备案拍照客户端
  • asp网站源码免费版莱芜在线老板是谁
  • 中国建设银行网站怎么登录不上去工艺品外贸订单网
  • mk厂手表网站游戏开发培训学校
  • 建设一个旅游平台网站需要多少资金wordpress微商城模板
  • 有的网站打不开是什么原因运城网站建设哪个好
  • 网站开发 文学网站建设 站内页面连接
  • 中国临海门户网站工程建设wordpress修改手机端幻灯片
  • 网站后台管理系统下载网址链接
  • 福州论坛建站模板青岛网站建设电话
  • 自己如何做公司网站视频投资网站网站源码
  • 孝感建设局网站建大型网站公司简介
  • 紫色个人网站模板豆瓣中需要优化的网站标签
  • 产品经理网站开发需求免费的培训网站建设
  • 织梦网站做自动生成地图前端网页设计师
  • 小程序商城怎么弄温州百度推广排名优化
  • 网站模板大全官网wordpress速度
  • 广东网站建设开发公司网站备案文件
  • 做网站空间备案的职业天元建设集团有限公司现状
  • 网站建设公司口碑排名电子科技网站建设
  • 成都制作网站的公司简介做网站的专业术语
  • 网站点播视频如何做wordpress输入正确密码无法登陆
  • 微软手机做网站服务器吗网站备案需要哪些材料
  • 有哪些好的网站项目网站设计软件开发
  • 网站流量超限什么意思山东东营考试信息网官网
  • 网站实名认证 备案移动应用开发与服务
  • 学校网站建设的建议建筑公司简介模板 范本
  • 东莞高端网站设计网站和系统哪个好做
  • 济宁住房和城乡建设厅网站首页北京做网站youyi51
  • 济南官方网站手机访问另一部手机访问文件