我看到的大多数示例和流行的智慧都使用类中小部件的典型模板,其中所有进一步的小部件都是在 build 方法中创建的(我认为这可以使代码更清晰,但把它放在一边)。
但是,如果引用的小部件不会进一步更改,它仍然会在每次构建调用时重新创建。在 initState 或类构造函数中分配 this 并稍后引用它是否有任何实际问题?
简单的例子
// this partial from inside the build() method currently
Container(
padding: const EdgeInsets.only(bottom: 8.0),
child: Text(
'Oeschinen Lake Campground',
style: TextStyle(
fontWeight: FontWeight.bold,
),
),
),
到
// Now inside initState or class Constructor
myText = Text(
'Oeschinen Lake Campground',
style: TextStyle(
fontWeight: FontWeight.bold,
),
);
...
// Still inside build method (in fact this could also go inside the constructor ?)
Container(
padding: const EdgeInsets.only(bottom: 8.0),
child: myText
)
这仅适用于不基于状态引用的代码。
这样做除了设计/美学之外还有其他缺点吗?虽然这个例子是微不足道的,但我一直在想,当应用程序变得更加复杂时,不必继续重建非基于状态的小部件可能会有一些性能/电池/顶部空间的好处(我也知道我认为小部件进一步在树上可能仍然每次都需要一个新对象)。但是,我是 Flutter/dart 的新手,所以对一些我没有正确考虑或从根本上误解了某些方面的问题保持警惕。
最佳答案
TL;DR:不要。
首先,让我们看看 Google 员工和 Flutter 工程师 Matt Sullivan has to say about this topic:
With Flutter creating and destroying objects with great frequency, should developers take steps to limit this behavior? It’s not uncommon to see new Flutter developers create references to widgets they know will not change over time, and place them in state so that they won’t be destroyed and rebuilt.
Don’t do this.
为了理解为什么这是一个坏主意,您首先需要了解 Widget 的作用很少。
因为它们通常只是组合其他 Widgets 或实例化 RenderObjects,它们并不进行实际的渲染;所有繁重的工作都由 RenderObject 完成。
您可以将 Widgets 视为 RenderObjects 的超轻量级“蓝图”。
另请注意,Flutter 框架本身会大量缓存 RenderObject,因此如果您在连续构建中创建一些类似的 Widget,则底层 RenderObject is automatically reused .
通过缓存 UI,您可以有效地重新创建 Flutter 的渲染管道提供的开箱即用的功能。
正因为如此,很多人会认为增加代码的复杂性是不值得的。
“好吧,”你可能会想, “性能优势可能非常非常小,但确实存在,对吧?”
实际上,没有。
这是因为底层的 Dart 运行时使用两种类型的垃圾收集器:Young Space Scavenger 垃圾收集器用于短期对象,mark-sweep 垃圾收集器用于长期对象.
有关它们如何工作的更详细说明,请查看恰当命名为“Don't Fear the Garbage Collector”的 this article。
基本上,它说 Young Space Scavenger 比 mark-sweep 收集器快得多,并且如果应用程序不遵守“弱代际假设”,该假设表明大多数对象在年轻时就死了,那么标记清除会更频繁地发生。
简而言之,性能实际上可能会变差。
总而言之,重新实现内置的 Flutter 功能,同时降低代码的可读性和应用程序的速度可能不是正确的方法。
关于flutter - 在 initState 或类构造函数中定义小部件而不是构建?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52856438/
我正在尝试设置一个puppet节点,但rubygems似乎不正常。如果我通过它自己的二进制文件(/usr/lib/ruby/gems/1.8/gems/facter-1.5.8/bin/facter)在cli上运行facter,它工作正常,但如果我通过由rubygems(/usr/bin/facter)安装的二进制文件,它抛出:/usr/lib/ruby/1.8/facter/uptime.rb:11:undefinedmethod`get_uptime'forFacter::Util::Uptime:Module(NoMethodError)from/usr/lib/ruby
我在我的项目中添加了一个系统来重置用户密码并通过电子邮件将密码发送给他,以防他忘记密码。昨天它运行良好(当我实现它时)。当我今天尝试启动服务器时,出现以下错误。=>BootingWEBrick=>Rails3.2.1applicationstartingindevelopmentonhttp://0.0.0.0:3000=>Callwith-dtodetach=>Ctrl-CtoshutdownserverExiting/Users/vinayshenoy/.rvm/gems/ruby-1.9.3-p0/gems/actionmailer-3.2.1/lib/action_mailer
我想向我的Controller传递一个参数,它是一个简单的复选框,但我不知道如何在模型的form_for中引入它,这是我的观点:{:id=>'go_finance'}do|f|%>Transferirde:para:Entrada:"input",:placeholder=>"Quantofoiganho?"%>Saída:"output",:placeholder=>"Quantofoigasto?"%>Nota:我想做一个额外的复选框,但我该怎么做,模型中没有一个对象,而是一个要检查的对象,以便在Controller中创建一个ifelse,如果没有检查,请帮助我,非常感谢,谢谢
我已经从我的命令行中获得了一切,所以我可以运行rubymyfile并且它可以正常工作。但是当我尝试从sublime中运行它时,我得到了undefinedmethod`require_relative'formain:Object有人知道我的sublime设置中缺少什么吗?我正在使用OSX并安装了rvm。 最佳答案 或者,您可以只使用“require”,它应该可以正常工作。我认为“require_relative”仅适用于ruby1.9+ 关于ruby-主要:Objectwhenrun
我想在一个没有Sass引擎的类中使用Sass颜色函数。我已经在项目中使用了sassgem,所以我认为搭载会像以下一样简单:classRectangleincludeSass::Script::FunctionsdefcolorSass::Script::Color.new([0x82,0x39,0x06])enddefrender#hamlengineexecutedwithcontextofself#sothatwithintemlateicouldcall#%stop{offset:'0%',stop:{color:lighten(color)}}endend更新:参见上面的#re
我正在尝试用ruby中的gsub函数替换字符串中的某些单词,但有时效果很好,在某些情况下会出现此错误?这种格式有什么问题吗NoMethodError(undefinedmethod`gsub!'fornil:NilClass):模型.rbclassTest"replacethisID1",WAY=>"replacethisID2andID3",DELTA=>"replacethisID4"}end另一个模型.rbclassCheck 最佳答案 啊,我找到了!gsub!是一个非常奇怪的方法。首先,它替换了字符串,所以它实际上修改了
我有一些代码在几个不同的位置之一运行:作为具有调试输出的命令行工具,作为不接受任何输出的更大程序的一部分,以及在Rails环境中。有时我需要根据代码的位置对代码进行细微的更改,我意识到以下样式似乎可行:print"Testingnestedfunctionsdefined\n"CLI=trueifCLIdeftest_printprint"CommandLineVersion\n"endelsedeftest_printprint"ReleaseVersion\n"endendtest_print()这导致:TestingnestedfunctionsdefinedCommandLin
我有一个只接受一个参数的方法:defmy_method(number)end如果使用number调用方法,我该如何引发错误??通常,我如何定义方法参数的条件?比如我想在调用的时候报错:my_method(1) 最佳答案 您可以添加guard在函数的开头,如果参数无效则引发异常。例如:defmy_method(number)failArgumentError,"Inputshouldbegreaterthanorequalto2"ifnumbereputse.messageend#=>Inputshouldbegreaterthano
我使用Ember作为我的前端和GrapeAPI来为我的API提供服务。前端发送类似:{"service"=>{"name"=>"Name","duration"=>"30","user"=>nil,"organization"=>"org","category"=>nil,"description"=>"description","disabled"=>true,"color"=>nil,"availabilities"=>[{"day"=>"Saturday","enabled"=>false,"timeSlots"=>[{"startAt"=>"09:00AM","endAt"=>
我想获取模块中定义的所有常量的值:moduleLettersA='apple'.freezeB='boy'.freezeendconstants给了我常量的名字:Letters.constants(false)#=>[:A,:B]如何获取它们的值的数组,即["apple","boy"]? 最佳答案 为了做到这一点,请使用mapLetters.constants(false).map&Letters.method(:const_get)这将返回["a","b"]第二种方式:Letters.constants(false).map{|c