ARTICLE · 1198706
同一个过程,两种调用方式:App Inventor 里该用哪种?
👆 阅读之前记得关注+星标 ⭐️😄 每天才能第一时间接收到更新
摘要: 有用户在社区问:直接「调用 过程名」和「调用过程 + 获取过程 + 输入列表」都能用,性能、效率、使用场景上有什么不同?结论是:平时用前一种。只有要调用哪个过程得等运行时才知道,才用后一种。
先看用户的问题
社区里有位用户写了一个「创建工作模式参数字典」过程,有 modeID、modeName、dripRate、duration 四个参数,返回一个参数字典。然后用两种方式各调用了一次:
• 上面一块是常见的「调用 创建工作模式参数字典」,四个参数各占一个插槽,填进 1、「日常消毒」、6、600;
• 下面一块是「调用过程」,过程处接一块「获取过程」,在下拉框里选中同一个过程;输入列表处用「创建列表」装进 2、「终末消毒」、7、1200。
两块都能跑,返回的字典也一样。用户想知道:既然效果相同,在性能、效率和使用场景上有没有大的差别?
▲ 用户提问时附的两种写法(社区原图)
本质区别:一个是静态调用,一个是动态调用
直接调用在写积木时就确定了要调哪个过程。编译后,它就是一句普通的函数调用,参数直接传进去,中间没有其它步骤。
动态调用把「过程」当成一个值来用,运行时要走三步:
1. 「获取过程」把过程包装成一个过程对象。这块积木每执行一次,就新建一个对象;
2. 「创建列表」把四个参数装进一个新列表;
3. 「调用过程」把列表转成参数数组,检查参数个数对不对,再间接调用那个过程。
所以动态调用比直接调用多了好几个步骤。不过这些开销有多大呢?
▲ 动态调用多出来的步骤(示意图)
性能:差别真实存在,但感觉不到
多出来的这几步都是微秒级的。点按钮、切换模式这类一秒钟也点不了几次的操作,两种写法用起来没有任何区别。
只有放进循环里调用几千上万次,或者放在间隔很短的计时器里,才值得考虑这点开销。这种情况一律用直接调用。如果确实需要动态调用,也要在循环外先「获取过程」存进变量,循环里只调用,不要每次都新建过程对象。
比性能更重要的是:出了错能不能及早发现
真正该关心的不是快慢,而是写错了能不能及早发现:
参数个数不对,会在运行时弹出「not enough arguments」或「too many arguments」。参数顺序写反最麻烦:程序照常运行,只是消毒时长变成了滴速,这种问题最难查。
直接调用:绝大多数情况
像这位用户的场景,「日常消毒」「终末消毒」只是用同一个过程、换不同的参数,直接调用两次就行:
▲ 直接调用两次,只换参数
模式多了也不用改成动态调用。可以把参数写成一张表,用循环逐行取出后直接调用:
▲ 参数写成表,循环直接调用
这里要变的是「数据」,过程始终是同一个,所以直接调用就够了。
动态调用:要调用的过程会变时才用
什么时候该用「调用过程 + 获取过程」?判断标准只有一条:要调用哪个过程,写积木时还定不下来。 比如:
• 按选择执行不同过程:把「日常消毒」「终末消毒」「设备自检」三个过程放进字典,键是模式名、值是过程。用户选了哪项,就取出对应的过程来调用,省掉一长串「如果…否则如果…」;
• 把过程当参数传递(回调):写一个通用过程,比如「倒计时结束后执行某件事」,具体执行什么,由调用方传进来一个过程决定;
• 参数本来就是一个列表:参数从文件、网络或数据库读进来时已经是列表,可以整个作为输入列表传进去,不用一个个拆开;
• 按名字调用:用「按名称获取过程」,传入文本形式的过程名,比如名字来自配置文件。这种写法最灵活,也最容易出错:名字写错一个字,要到运行时才报错。
▲ 按选择调用不同过程(示意图)
结论
两种写法效果相同,性能差别小到可以忽略。真正的区别在于,直接调用的错误编辑器能当场提示,动态调用的错误往往要到运行时才暴露。
所以:平时一律用直接调用;只有确实需要「运行时决定调哪个过程」时,再用调用过程 + 获取过程。
好了,是不是很简单,今天的分享就到此结束,咱们下回见;
如果觉得文章对你有帮助,记得点.赞.转.发.收.藏喔!















































































