text: (window.webpackJsonp=window.webpackJsonp||[]).push([[37],{400:function(e,t,_){"use strict";_.r(t);var v=_(42),d=Object(v.a)({},(function(){var e=this,t=e.$createElement,_=e._self._c||t;return _("ContentSlotsDistributor",{attrs:{"slot-key":e.$parent.slotKey}},[_("h1",{attrs:{id:"widget-渲染策略"}},[_("a",{staticClass:"header-anchor",attrs:{href:"#widget-渲染策略"}},[e._v("#")]),e._v(" Widget 渲染策略")]),e._v(" "),_("p",[e._v("主要讲述：")]),e._v(" "),_("ul",[_("li",[e._v("Stateful和Stateless")]),e._v(" "),_("li",[e._v("Key")]),e._v(" "),_("li",[e._v("buildContext")]),e._v(" "),_("li",[e._v("setState")]),e._v(" "),_("li",[e._v("InheritedWidget")]),e._v(" "),_("li",[e._v("Element")]),e._v(" "),_("li",[e._v("RenderObject")]),e._v(" "),_("li",[e._v("SteamBuilder")])]),e._v(" "),_("h3",{attrs:{id:"widget"}},[_("a",{staticClass:"header-anchor",attrs:{href:"#widget"}},[e._v("#")]),e._v(" Widget")]),e._v(" "),_("ul",[_("li",[e._v("为Element提供配置信息，通过State管理状态")]),e._v(" "),_("li",[_("code",[e._v("StatefulWidget")]),e._v("通过 "),_("code",[e._v("key")]),e._v(" 和 "),_("code",[e._v("runtimeType")]),e._v(" 来判断是否"),_("code",[e._v("canUpdate")])]),e._v(" "),_("li",[_("code",[e._v("StatelessWidget")]),e._v("是不变的，不能多次渲染，只能被替换")])]),e._v(" "),_("p",[e._v("Stateful的Widget可以多次绘制更新。（运行时和setState时都会调用build方法）")]),e._v(" "),_("p",[e._v("每次绘制都会进入更新算法"),_("code",[e._v("canUpdate")]),e._v("：会比较"),_("code",[e._v("runtimeType (组件的类型和子元素的引用)")]),e._v(" 和 "),_("code",[e._v("key")])]),e._v(" "),_("div",{staticClass:"language- extra-class"},[_("pre",{pre:!0,attrs:{class:"language-text"}},[_("code",[e._v("   static bool canUpdate(Widget oldWidget, Widget newWidget) {\n    return oldWidget.runtimeType == newWidget.runtimeType\n        && oldWidget.key == newWidget.key;\n  }\n")])])]),_("p",[e._v("key的种类（功能和名字一致）")]),e._v(" "),_("ul",[_("li",[e._v("ValueKey")]),e._v(" "),_("li",[e._v("ObjectKey")]),e._v(" "),_("li",[e._v("UniqueKey")]),e._v(" "),_("li",[e._v("PageStorageKey")]),e._v(" "),_("li",[e._v("GlobalKey")])]),e._v(" "),_("p",[e._v("如果要重绘"),_("code",[e._v("Stateless")]),e._v("的Widget，那么必须创建新的实例。当然在"),_("code",[e._v("Stateless")]),e._v("中也并不需要使用"),_("code",[e._v("key")]),e._v("，")]),e._v(" "),_("p",[e._v("每个widget都有自己的context。这个context是父组件通过build方法给他返回的。比如context不匹配时调用"),_("code",[e._v("showSnackBar")]),e._v("方法会提示："),_("code",[e._v("Scaffold.of() called with a context that does not contain a Scaffold")]),e._v("。")]),e._v(" "),_("p",[e._v("解决方法：")]),e._v(" "),_("ol",[_("li",[e._v("可以通过 "),_("code",[e._v("new Builder(builder: (context) {...})")]),e._v(" 获得context。")]),e._v(" "),_("li",[e._v("或者将不能使用获取context的方法使用widget单独build")]),e._v(" "),_("li",[e._v("使用"),_("code",[e._v("GlobalKey<ScaffoldState>()")]),e._v("，通过key来调用")])]),e._v(" "),_("p",[e._v("因为每个build的context不一样，所以每个不同的页面数据无法共享。（InheritedWidget 等除外）")]),e._v(" "),_("p",[e._v("然后，官方提出了"),_("code",[e._v("InheritedWidget")]),e._v("的类，"),_("strong",[e._v("共享的State放在一个继承InheritedWidget的类中")]),e._v("，随之社区推出了"),_("a",{attrs:{href:"https://pub.dartlang.org/packages/scoped_model",target:"_blank",rel:"noopener noreferrer"}},[e._v("scoped_model"),_("OutboundLink")],1),e._v("的库（比Redux方便）")]),e._v(" "),_("p",[e._v("但是还是会存在整棵树的Widget都会更新，虽然在"),_("code",[e._v("ScopedModelDescendant")]),e._v("中有"),_("code",[e._v("rebuildOnChange")]),e._v("来阻止重新渲染（类似React的shouldComponentUpdate，当然它有竞态的问题）")]),e._v(" "),_("p",[e._v("不过，Scope model 使用起来很方便，如果不是复杂项目，使用 Scope model 会"),_("strong",[e._v("容易上手")]),e._v("。")]),e._v(" "),_("h3",{attrs:{id:"element："}},[_("a",{staticClass:"header-anchor",attrs:{href:"#element："}},[e._v("#")]),e._v(" Element：")]),e._v(" "),_("ul",[_("li",[_("code",[e._v("管理")]),e._v("底层渲染树")]),e._v(" "),_("li",[e._v("最重要的属性："),_("code",[e._v("dirty")]),e._v(" 是否渲染的关键")]),e._v(" "),_("li",[e._v("调用"),_("code",[e._v("setState({})")]),e._v("会执行"),_("code",[e._v("markNeedsBuild")]),e._v("标记自身为"),_("code",[e._v("dirty = true")]),e._v("，")]),e._v(" "),_("li",[_("code",[e._v("dirty = true")]),e._v("意味着会在系统下一个事件周期中重绘，会调用"),_("code",[e._v("build")]),e._v("方法")])]),e._v(" "),_("h3",{attrs:{id:"renderobject："}},[_("a",{staticClass:"header-anchor",attrs:{href:"#renderobject："}},[e._v("#")]),e._v(" RenderObject：")]),e._v(" "),_("ul",[_("li",[e._v("主要负责"),_("code",[e._v("渲染")]),e._v("工作")]),e._v(" "),_("li",[e._v("相当于 render树上的 一个节点")])]),e._v(" "),_("h3",{attrs:{id:"steambuilder"}},[_("a",{staticClass:"header-anchor",attrs:{href:"#steambuilder"}},[e._v("#")]),e._v(" SteamBuilder()")]),e._v(" "),_("p",[e._v("BloC即（Business Logic Component），是一种利用reactive programming方式构建应用的方法，这是一个由流构成的完全异步的世界。")]),e._v(" "),_("ul",[_("li",[e._v("用StreamBuilder包裹有状态的部件，streambuilder将会监听一个流")]),e._v(" "),_("li",[e._v("这个流来自于BLoC")]),e._v(" "),_("li",[e._v("有状态小部件中的数据来自于监听的流。")]),e._v(" "),_("li",[e._v("用户交互手势被检测到，产生了事件。例如按了一下按钮。")]),e._v(" "),_("li",[e._v("调用bloc的功能来处理这个事件")]),e._v(" "),_("li",[e._v("在bloc中处理完毕后将会吧最新的数据add进流的sink中")]),e._v(" "),_("li",[e._v("StreamBuilder监听到新的数据，产生一个新的snapshot，并重新调用build方法")]),e._v(" "),_("li",[e._v("Widget被重新构建")])]),e._v(" "),_("p",[_("a",{attrs:{href:"https://juejin.im/post/5bb6f344f265da0aa664d68a",target:"_blank",rel:"noopener noreferrer"}},[e._v("参考链接"),_("OutboundLink")],1)])])}),[],!1,null,null,null);t.default=d.exports}}]);