Login

UI 代码的载入顺序

原文:UI_Code_Load_Order,发表于 WoWWiki

译者:流润之风

本文描述了 XML 文件解析载入行为的先后顺序,此外,也会涵盖插件和文件的载入顺序。

单个插件内的各文件

在单个插件之内(或在 FrameXML 之内),载入是按照 .toc 文件中定义的顺序线性进行的。toc 中定义的第一个文件最先被解析执行,之后是第二个,然后是第三个,依此类推。对于 XML 文件,每当执行到其中包含的 <Script file="X"/> 元素,就会去解析和执行引用的文件 X,处理完后才会接着处理后面的元素。因而,如果有以下的 toc 结构:

File1.lua
File2.lua
File3.xml
File4.xml
File5.lua

而且 File3.xml 包含了:

  • <Script file="FileA.lua"/> 和

  • <Script file="FileB.lua"/>,

File4.xml 包含了:

  • <Script file="FileA.lua"/> 和

  • <Script file="FileC.lua"/>

那么,载入/执行的顺序将会是:

  1. File1.lua
  2. File2.lua
  3. File3.xml
    1. 开始
    2. FileA.lua
    3. FileB.lua
    4. File3.xml 的其余部分
  4. File4.xml
    1. 开始
    2. FileA.lua
    3. FileC.lua
    4. File4.xml 的其余部分
  5. File5.lua

可以看到,我们完全能够预计到整个载入过程的先后顺序,另外,FileA.lua 执行了两次。因而,当你想在 XML 中包含 <Script> 代码时一定要谨慎。

LUA 文件的处理

lua 文件由 lua 引擎解析执行。所有的内嵌代码会马上执行(事实上,这是函数定义如何发生的方式--简单地执行)

XML文件的处理

XML 文件按元素的先后顺序进行处理

Script元素

如上文所述,<Script.../> 元素会在遇到时立即得到处理。它们只能出现在文件的开头部分,通常用于执行某些设置代码、或是包含某个 lua 文件(对于这种情况要谨慎,因为有可能会对一个 lua 文件载入多次)。

虚元素

虚框体元素在解析之后存储下来,以备后用,它们无法自我执行,不会产生任何 LUA 对象。而只是创建出一个可供以后使用的模板。虚框体的定义会在插件载入批处理过程结束时丢弃,关于批处理下面会有更详细的解释,从本质上来说,游戏登录就是一个批处理过程,游戏运行后每个 LoadOnDemand 调用(以及该调用所执行的嵌套载入)也都是独立的批处理过程。

一般元素和继承元素

所有的一般元素和继承元素按照以下步骤进行递归处理:

  1. 创建适当的 C++ 对象和 lua 引用(记住,不能锚固到一个尚未创建的框体上)
  2. 如果该框体继承自某个虚模板,那么先将这些规则应用到模板上,再继续。
  3. 如果该框体有子框体,那么按照子框体在 XML 文件中出现的顺序将规则应用到所有子框体上。
  4. 将所有脚本处理器应用到框体上
  5. 调用框体的 OnLoad 处理器.

考虑以下的结构:

<Frame name="V1" virtual="true">
  <Frames>
    <Frame name="$parent_V1_C1"/>
    <Frame name="$parent_V1_C2"/>
  </Frames>
</Frame>

<Frame name="V2" inherits="V1" virtual="true">
  <Frames>
    <Frame name="$parent_V2_C1"/>
    <Frame name="$parent_V2_C2" inherits="V1"/>
  </Frames>
</Frame>

<Frame name="F" inherits="V2">
  <Frames>
    <Frame name="$parent_C1" inherits="V1"/>
    <Frame name="$parent_C2"/>
  </Frames>
</Frame>

创建/载入的顺序将会是:

  1. Create F
    1. Create F_V1_C1
    2. OnLoad F_V1_C1

    3. Create F_V1_C2
    4. OnLoad F_V1_C2

    5. Create F_V2_C1
    6. OnLoad F_V2_C1

    7. Create F_V2_C2
      1. Create F_V2_C2_V1_C1
      2. OnLoad F_V2_C2_V1_C1

      3. Create F_V2_C2_V1_C2
      4. OnLoad F_V2_C2_V1_C2

      5. OnLoad F_V2_C2

    8. Create F_C1
    9. Create F_C1_V1_C1
      1. OnLoad F_C1_V1_C1

      2. Create F_C1_V1_C2
      3. OnLoad F_C1_V1_C2

      4. OnLoad F_C1

    10. Create F_C2
    11. OnLoad F_C2

  2. OnLoad F

插件的载入顺序

先把按需载入的插件放到一边,最先载入的是 FrameXML(它其实并不是插件,但是有着类似插件的结构和载入方式),然后是其他插件,它们按照操作系统返回的顺序进行处理(对于一般的 Windows 版本来说,也就是目录项顺序,最先放入插件目录的插件会被最先载入,如果删除了某个目录,那么会将空位保留给下一个新加入的目录。该顺序又被称为未排序顺序),并遵循以下基本原则:

  1. 如果插件已被载入(或正在载入),那么不再载入。
  2. 如果插件有未载入的依赖项,那么按这些依赖项在 .toc 中的顺序进行载入
  3. 如果插件有未载入、已激活、可选的依赖项,那么按这些依赖项在 .toc 中的顺序进行载入
  4. 如前所述,按 .toc 中的排列顺序载入各插件文件
  5. 如果有其他未载入、已激活的插件,且标记为 LoadWith 本插件(随同本插件载入),那么处理它们(处理顺序未知,我想是文件系统的自然顺序)。

按照这些规则,将所有的插件以合理的顺序进行载入,使各插件的依赖项优先载入。

按需载入的 插件

按需载入要更加复杂一些,因为它们在需要时才进行初始化,而且在插件(和所有子插件)的载入过程结束以前 Load 插件函数将保持阻塞。调用 Load 之后,遵循与上述过程相同的规则进行载入处理,而且在该过程完成之前,Load 函数不会返回。


插件开发资料类, 流润之风

UI代码的载入顺序 (last edited 2008-06-22 14:12:25 by 月色狼影)