# 生命周期

> 从启动引导到组件 —— Main、Window.onShow 以及 onAdd(firstTime)/onRemove 钩子。

Source: https://crossfly.dev/zh/docs/concepts/lifecycle — CrossFly documentation. Full docs as one file: https://crossfly.dev/llms-full.txt

# 生命周期

CrossFly 的生命周期分为三个层级：**应用**、**窗口**（屏幕）和**组件**。

## 层级 1 —— 应用：启动引导（`Main`）
`Main` 是 libGDX 的 `ApplicationListener`。当平台启动时，libGDX 在
paint thread 上调用 `Main.create()`，随后 `Main`：
1. 检测平台并初始化运行时和设备配置；
2. 解析**主窗口**的名称（来自 `classname` 参数或 `getMainWindow()`）；
3. **通过反射实例化该窗口**（`Class.forName(...)` → `newInstance()`）并调用其 `onShow()`。

在此之后，libGDX 会调用 `render()`（在每个渲染帧）和 `resize()` —— 始终在 paint thread 上。

## 层级 2 —— 窗口：`onShow()`
每个屏幕都是 `Window` 的子类，它**在 `onShow()` 中搭建自己的 UI**（并调用 `super.onShow()`）：
```java
public class TelaHome extends Window {
   @Override public void onShow() throws Exception {
      super.onShow();
      setLayout(new VerticalLayout());
      add(LAY_AUTO, new Label("Início"));
   }
}
```
**为什么用 `onShow()` 而不是构造函数？** 在构造函数中，**边界和层级尚未
就绪** —— `Screen.width/height` 和窗口尺寸只有之后才有效。过早搭建 UI
会导致测量错误。（窗口栈与导航见 [窗口栈](/docs/ui/navigation/the-window-stack)。）

## 层级 3 —— 组件：`onAdd(firstTime)` / `onRemove()`
当一个组件进入树时，框架会调用 **`onAdd(boolean firstTime)`**；当它离开时，调用
**`onRemove()`**。你就在这里初始化并释放资源：
```java
public class Relogio extends Component {
   private Timer timer;
   @Override public void onAdd(boolean firstTime) throws Exception {
      super.onAdd(firstTime);
      if (firstTime) timer = iniciarTimer();   // 只应存在一次的资源
   }
   @Override public void onRemove() {
      if (timer != null) timer.cancel();        // 退出时务必释放
      super.onRemove();
   }
}
```
**`firstTime` 区分了什么？** 一个组件可以被添加、移除，再**重新添加**。
`firstTime == true` 只在第一次成立 —— 用它来做不应重复的初始化。`onRemove()` 是
清理的对应方：取消定时器、监听器、光标。

> 通用规则：**不要**在构造函数中初始化 UI/资源。使用 `onShow()`（窗口）和
> `onAdd(firstTime)`（组件），在那里边界和层级已经有效。

<div class="cf-diagram">
<svg role="img" id="my-svg" width="272" height="602" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" class="flowchart" style="max-width: 272px; background-color: transparent;" viewBox="0 0 272 602" role="graphics-document document" aria-roledescription="flowchart-v2"><style>#my-svg{font-family:Manrope,system-ui,sans-serif;font-size:14px;fill:var(--text);}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#my-svg .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#my-svg .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#my-svg .error-icon{fill:var(--bg-elev);}#my-svg .error-text{fill:var(--text-dim);stroke:var(--text-dim);}#my-svg .edge-thickness-normal{stroke-width:1px;}#my-svg .edge-thickness-thick{stroke-width:3.5px;}#my-svg .edge-pattern-solid{stroke-dasharray:0;}#my-svg .edge-thickness-invisible{stroke-width:0;fill:none;}#my-svg .edge-pattern-dashed{stroke-dasharray:3;}#my-svg .edge-pattern-dotted{stroke-dasharray:2;}#my-svg .marker{fill:var(--text-dim);stroke:var(--text-dim);}#my-svg .marker.cross{stroke:var(--text-dim);}#my-svg svg{font-family:Manrope,system-ui,sans-serif;font-size:14px;}#my-svg p{margin:0;}#my-svg .label{font-family:Manrope,system-ui,sans-serif;color:var(--text);}#my-svg .cluster-label text{fill:var(--text-dim);}#my-svg .cluster-label span{color:var(--text-dim);}#my-svg .cluster-label span p{background-color:transparent;}#my-svg .label text,#my-svg span{fill:var(--text);color:var(--text);}#my-svg .node rect,#my-svg .node circle,#my-svg .node ellipse,#my-svg .node polygon,#my-svg .node path{fill:var(--bg-soft);stroke:var(--border-strong);stroke-width:1px;}#my-svg .rough-node .label text,#my-svg .node .label text,#my-svg .image-shape .label,#my-svg .icon-shape .label{text-anchor:middle;}#my-svg .node .katex path{fill:var(--text-dim);stroke:var(--text-dim);stroke-width:1px;}#my-svg .rough-node .label,#my-svg .node .label,#my-svg .image-shape .label,#my-svg .icon-shape .label{text-align:center;}#my-svg .node.clickable{cursor:pointer;}#my-svg .root .anchor path{fill:var(--text-dim)!important;stroke-width:0;stroke:var(--text-dim);}#my-svg .arrowheadPath{fill:rgba(255, 255, 255, 0);}#my-svg .edgePath .path{stroke:var(--text-dim);stroke-width:1px;}#my-svg .flowchart-link{stroke:var(--text-dim);fill:none;}#my-svg .edgeLabel{background-color:var(--bg-elev);text-align:center;}#my-svg .edgeLabel p{background-color:var(--bg-elev);}#my-svg .edgeLabel rect{opacity:0.5;background-color:var(--bg-elev);fill:var(--bg-elev);}#my-svg .labelBkg{background-color:rgba(255, 255, 255, 0.5);}#my-svg .cluster rect{fill:var(--bg-elev);stroke:hsl(0, 0%, 90%);stroke-width:1px;}#my-svg .cluster text{fill:var(--text-dim);}#my-svg .cluster span{color:var(--text-dim);}#my-svg div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:Manrope,system-ui,sans-serif;font-size:12px;background:var(--bg-elev);border:1px solid hsl(0, 0%, 90%);border-radius:2px;pointer-events:none;z-index:100;}#my-svg .flowchartTitleText{text-anchor:middle;font-size:18px;fill:var(--text);}#my-svg rect.text{fill:none;stroke-width:0;}#my-svg .icon-shape,#my-svg .image-shape{background-color:var(--bg-elev);text-align:center;}#my-svg .icon-shape p,#my-svg .image-shape p{background-color:var(--bg-elev);padding:2px;}#my-svg .icon-shape .label rect,#my-svg .image-shape .label rect{opacity:0.5;background-color:var(--bg-elev);fill:var(--bg-elev);}#my-svg .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#my-svg .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#my-svg .node .neo-node{stroke:var(--border-strong);}#my-svg [data-look="neo"].node rect,#my-svg [data-look="neo"].cluster rect,#my-svg [data-look="neo"].node polygon{stroke:url(#my-svg-gradient);filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#my-svg [data-look="neo"].swimlane.cluster rect{filter:none;}#my-svg [data-look="neo"].node path{stroke:url(#my-svg-gradient);stroke-width:1px;}#my-svg [data-look="neo"].node .outer-path{filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#my-svg [data-look="neo"].node .neo-line path{stroke:var(--border-strong);filter:none;}#my-svg [data-look="neo"].node circle{stroke:url(#my-svg-gradient);filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#my-svg [data-look="neo"].node circle .state-start{fill:var(--text-dim);}#my-svg [data-look="neo"].icon-shape .icon{fill:url(#my-svg-gradient);filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#my-svg [data-look="neo"].icon-shape .icon-neo path{stroke:url(#my-svg-gradient);filter:drop-shadow( 1px 2px 2px rgba(185,185,185,1));}#my-svg :root{--mermaid-font-family:Manrope,system-ui,sans-serif;}</style><g><marker id="my-svg_flowchart-v2-pointEnd" class="marker flowchart-v2" viewBox="0 0 10 10" refX="5" refY="5" markerUnits="userSpaceOnUse" markerWidth="8" markerHeight="8" orient="auto"><path d="M 0 0 L 10 5 L 0 10 z" class="arrowMarkerPath" style="stroke-width: 1; stroke-dasharray: 1, 0;"/></marker><marker id="my-svg_flowchart-v2-pointStart" class="marker flowchart-v2" viewBox="0 0 10 10" refX="4.5" refY="5" markerUnits="userSpaceOnUse" markerWidth="8" markerHeight="8" orient="auto"><path d="M 0 5 L 10 10 L 10 0 z" class="arrowMarkerPath" style="stroke-width: 1; stroke-dasharray: 1, 0;"/></marker><marker id="my-svg_flowchart-v2-pointEnd-margin" class="marker flowchart-v2" viewBox="0 0 11.5 14" refX="11.5" refY="7" markerUnits="userSpaceOnUse" markerWidth="10.5" markerHeight="14" orient="auto"><path d="M 0 0 L 11.5 7 L 0 14 z" class="arrowMarkerPath" style="stroke-width: 0; stroke-dasharray: 1, 0;"/></marker><marker id="my-svg_flowchart-v2-pointStart-margin" class="marker flowchart-v2" viewBox="0 0 11.5 14" refX="1" refY="7" markerUnits="userSpaceOnUse" markerWidth="11.5" markerHeight="14" orient="auto"><polygon points="0,7 11.5,14 11.5,0" class="arrowMarkerPath" style="stroke-width: 0; stroke-dasharray: 1, 0;"/></marker><marker id="my-svg_flowchart-v2-circleEnd" class="marker flowchart-v2" viewBox="0 0 10 10" refX="11" refY="5" markerUnits="userSpaceOnUse" markerWidth="11" markerHeight="11" orient="auto"><circle cx="5" cy="5" r="5" class="arrowMarkerPath" style="stroke-width: 1; stroke-dasharray: 1, 0;"/></marker><marker id="my-svg_flowchart-v2-circleStart" class="marker flowchart-v2" viewBox="0 0 10 10" refX="-1" refY="5" markerUnits="userSpaceOnUse" markerWidth="11" markerHeight="11" orient="auto"><circle cx="5" cy="5" r="5" class="arrowMarkerPath" style="stroke-width: 1; stroke-dasharray: 1, 0;"/></marker><marker id="my-svg_flowchart-v2-circleEnd-margin" class="marker flowchart-v2" viewBox="0 0 10 10" refY="5" refX="12.25" markerUnits="userSpaceOnUse" markerWidth="14" markerHeight="14" orient="auto"><circle cx="5" cy="5" r="5" class="arrowMarkerPath" style="stroke-width: 0; stroke-dasharray: 1, 0;"/></marker><marker id="my-svg_flowchart-v2-circleStart-margin" class="marker flowchart-v2" viewBox="0 0 10 10" refX="-2" refY="5" markerUnits="userSpaceOnUse" markerWidth="14" markerHeight="14" orient="auto"><circle cx="5" cy="5" r="5" class="arrowMarkerPath" style="stroke-width: 0; stroke-dasharray: 1, 0;"/></marker><marker id="my-svg_flowchart-v2-crossEnd" class="marker cross flowchart-v2" viewBox="0 0 11 11" refX="12" refY="5.2" markerUnits="userSpaceOnUse" markerWidth="11" markerHeight="11" orient="auto"><path d="M 1,1 l 9,9 M 10,1 l -9,9" class="arrowMarkerPath" style="stroke-width: 2; stroke-dasharray: 1, 0;"/></marker><marker id="my-svg_flowchart-v2-crossStart" class="marker cross flowchart-v2" viewBox="0 0 11 11" refX="-1" refY="5.2" markerUnits="userSpaceOnUse" markerWidth="11" markerHeight="11" orient="auto"><path d="M 1,1 l 9,9 M 10,1 l -9,9" class="arrowMarkerPath" style="stroke-width: 2; stroke-dasharray: 1, 0;"/></marker><marker id="my-svg_flowchart-v2-crossEnd-margin" class="marker cross flowchart-v2" viewBox="0 0 15 15" refX="17.7" refY="7.5" markerUnits="userSpaceOnUse" markerWidth="12" markerHeight="12" orient="auto"><path d="M 1,1 L 14,14 M 1,14 L 14,1" class="arrowMarkerPath" style="stroke-width: 2.5;"/></marker><marker id="my-svg_flowchart-v2-crossStart-margin" class="marker cross flowchart-v2" viewBox="0 0 15 15" refX="-3.5" refY="7.5" markerUnits="userSpaceOnUse" markerWidth="12" markerHeight="12" orient="auto"><path d="M 1,1 L 14,14 M 1,14 L 14,1" class="arrowMarkerPath" style="stroke-width: 2.5; stroke-dasharray: 1, 0;"/></marker><g class="root"><g class="clusters"/><g class="edgePaths"><path d="M136,57L136,61.167C136,65.333,136,73.667,136,81.333C136,89,136,96,136,99.5L136,103" id="my-svg-L_Create_Reflect_0" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_Create_Reflect_0" data-points="W3sieCI6MTM2LCJ5Ijo1N30seyJ4IjoxMzYsInkiOjgyfSx7IngiOjEzNiwieSI6MTA3fV0=" data-look="classic" marker-end="url(#my-svg_flowchart-v2-pointEnd)"/><path d="M136,156L136,160.167C136,164.333,136,172.667,136,180.333C136,188,136,195,136,198.5L136,202" id="my-svg-L_Reflect_Show_0" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_Reflect_Show_0" data-points="W3sieCI6MTM2LCJ5IjoxNTZ9LHsieCI6MTM2LCJ5IjoxODF9LHsieCI6MTM2LCJ5IjoyMDZ9XQ==" data-look="classic" marker-end="url(#my-svg_flowchart-v2-pointEnd)"/><path d="M136,255L136,259.167C136,263.333,136,271.667,136,279.333C136,287,136,294,136,297.5L136,301" id="my-svg-L_Show_Add_0" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_Show_Add_0" data-points="W3sieCI6MTM2LCJ5IjoyNTV9LHsieCI6MTM2LCJ5IjoyODB9LHsieCI6MTM2LCJ5IjozMDV9XQ==" data-look="classic" marker-end="url(#my-svg_flowchart-v2-pointEnd)"/><path d="M136,375L136,379.167C136,383.333,136,391.667,136,399.333C136,407,136,414,136,417.5L136,421" id="my-svg-L_Add_Live_0" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_Add_Live_0" data-points="W3sieCI6MTM2LCJ5IjozNzV9LHsieCI6MTM2LCJ5Ijo0MDB9LHsieCI6MTM2LCJ5Ijo0MjV9XQ==" data-look="classic" marker-end="url(#my-svg_flowchart-v2-pointEnd)"/><path d="M136,474L136,478.167C136,482.333,136,490.667,136,498.333C136,506,136,513,136,516.5L136,520" id="my-svg-L_Live_Remove_0" class="edge-thickness-normal edge-pattern-solid edge-thickness-normal edge-pattern-solid flowchart-link" style=";" data-edge="true" data-et="edge" data-id="L_Live_Remove_0" data-points="W3sieCI6MTM2LCJ5Ijo0NzR9LHsieCI6MTM2LCJ5Ijo0OTl9LHsieCI6MTM2LCJ5Ijo1MjR9XQ==" data-look="classic" marker-end="url(#my-svg_flowchart-v2-pointEnd)"/></g><g class="edgeLabels"><g class="edgeLabel"><g class="label" data-id="L_Create_Reflect_0" transform="translate(0, 0)"><foreignObject width="0" height="0"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"></span></div></foreignObject></g></g><g class="edgeLabel"><g class="label" data-id="L_Reflect_Show_0" transform="translate(0, 0)"><foreignObject width="0" height="0"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"></span></div></foreignObject></g></g><g class="edgeLabel"><g class="label" data-id="L_Show_Add_0" transform="translate(0, 0)"><foreignObject width="0" height="0"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"></span></div></foreignObject></g></g><g class="edgeLabel"><g class="label" data-id="L_Add_Live_0" transform="translate(0, 0)"><foreignObject width="0" height="0"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"></span></div></foreignObject></g></g><g class="edgeLabel"><g class="label" data-id="L_Live_Remove_0" transform="translate(0, 0)"><foreignObject width="0" height="0"><div xmlns="http://www.w3.org/1999/xhtml" class="labelBkg" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="edgeLabel"></span></div></foreignObject></g></g></g><g class="nodes"><g class="node default" id="my-svg-flowchart-Create-0" data-look="classic" transform="translate(136, 32.5)"><rect class="basic label-container" style="" x="-116.9765625" y="-24.5" width="233.953125" height="49"/><g class="label" style="" transform="translate(-88.9765625, -10.5)"><rect/><foreignObject width="177.953125" height="21"><div xmlns="http://www.w3.org/1999/xhtml" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="nodeLabel"><p>Main.create() (paint thread)</p></span></div></foreignObject></g></g><g class="node default" id="my-svg-flowchart-Reflect-1" data-look="classic" transform="translate(136, 131.5)"><rect class="basic label-container" style="" x="-119.5234375" y="-24.5" width="239.046875" height="49"/><g class="label" style="" transform="translate(-91.5234375, -10.5)"><rect/><foreignObject width="183.046875" height="21"><div xmlns="http://www.w3.org/1999/xhtml" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="nodeLabel"><p>通过反射实例化 MainWindow</p></span></div></foreignObject></g></g><g class="node default" id="my-svg-flowchart-Show-3" data-look="classic" transform="translate(136, 230.5)"><rect class="basic label-container" style="" x="-118.6796875" y="-24.5" width="237.359375" height="49"/><g class="label" style="" transform="translate(-90.6796875, -10.5)"><rect/><foreignObject width="181.359375" height="21"><div xmlns="http://www.w3.org/1999/xhtml" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="nodeLabel"><p>Window.onShow() — 构建 UI</p></span></div></foreignObject></g></g><g class="node default" id="my-svg-flowchart-Add-5" data-look="classic" transform="translate(136, 340)"><rect class="basic label-container" style="" x="-128" y="-35" width="256" height="70"/><g class="label" style="" transform="translate(-100, -21)"><rect/><foreignObject width="200" height="42"><div xmlns="http://www.w3.org/1999/xhtml" style="display: table; white-space: break-spaces; line-height: 1.5; max-width: 200px; text-align: center; width: 200px;"><span class="nodeLabel"><p>Component.onAdd(firstTime) — 每个子节点</p></span></div></foreignObject></g></g><g class="node default" id="my-svg-flowchart-Live-7" data-look="classic" transform="translate(136, 449.5)"><rect class="basic label-container" style="" x="-125.34375" y="-24.5" width="250.6875" height="49"/><g class="label" style="" transform="translate(-97.34375, -10.5)"><rect/><foreignObject width="194.6875" height="21"><div xmlns="http://www.w3.org/1999/xhtml" style="display: table-cell; white-space: nowrap; line-height: 1.5; max-width: 200px; text-align: center;"><span class="nodeLabel"><p>存活: onLayout / onPaint / 事件</p></span></div></foreignObject></g></g><g class="node default" id="my-svg-flowchart-Remove-9" data-look="classic" transform="translate(136, 559)"><rect class="basic label-container" style="" x="-128" y="-35" width="256" height="70"/><g class="label" style="" transform="translate(-100, -21)"><rect/><foreignObject width="200" height="42"><div xmlns="http://www.w3.org/1999/xhtml" style="display: table; white-space: break-spaces; line-height: 1.5; max-width: 200px; text-align: center; width: 200px;"><span class="nodeLabel"><p>Component.onRemove() — 释放资源</p></span></div></foreignObject></g></g></g></g></g><defs><filter id="my-svg-drop-shadow" height="130%" width="130%"><feDropShadow dx="4" dy="4" stdDeviation="0" flood-opacity="0.06" flood-color="var(--text-dim)"/></filter></defs><defs><filter id="my-svg-drop-shadow-small" height="150%" width="150%"><feDropShadow dx="2" dy="2" stdDeviation="0" flood-opacity="0.06" flood-color="var(--text-dim)"/></filter></defs><linearGradient id="my-svg-gradient" gradientUnits="objectBoundingBox" x1="0%" y1="0%" x2="100%" y2="0%"><stop offset="0%" stop-color="var(--border-strong)" stop-opacity="1"/><stop offset="100%" stop-color="hsl(0, 0%, 90%)" stop-opacity="1"/></linearGradient></svg>
</div>

## 参见
- 应用：[在屏幕间导航](/docs/ui/navigation/navigate-between-screens)
- 下一篇：[状态与数据流](/docs/concepts/state-and-data-flow)
