一、Component.onCompleted 详解
1.1 基本概念和作用
Component.onCompleted 是 QML 组件的生命周期钩子,在组件完全实例化并完成所有初始化后触发。
触发时机:
-
所有属性绑定已建立
-
所有子元素已创建
-
组件已完全构建并准备好使用
-
在父组件
onCompleted之前执行
1.2 基本使用
javascript
import QtQuick 2.15
Item {
id: root
width: 400
height: 400
Rectangle {
id: rect
width: 100
height: 100
color: "lightblue"
Component.onCompleted: {
console.log("Rectangle 已完全初始化");
console.log("当前颜色:", color);
console.log("父元素尺寸:", parent.width, "x", parent.height);
}
}
Component.onCompleted: {
console.log("根 Item 已完全初始化");
console.log("子元素数量:", children.length);
// 此时 rect 已经创建完成
console.log("rect 颜色:", rect.color);
}
}
1.3 执行顺序和层次关系
javascript
import QtQuick 2.15
Item {
id: level1
Component.onCompleted: console.log("Level 1 - 完成")
Item {
id: level2
Component.onCompleted: console.log("Level 2 - 完成")
Item {
id: level3
Component.onCompleted: console.log("Level 3 - 完成")
Rectangle {
id: level4
Component.onCompleted: console.log("Level 4 - 完成")
}
}
}
Text {
id: textItem
text: "Hello"
Component.onCompleted: console.log("Text 元素 - 完成")
}
}
// 输出顺序(从最深层到最外层):
// Level 4 - 完成
// Level 3 - 完成
// Level 2 - 完成
// Text 元素 - 完成
// Level 1 - 完成
1.4 动态创建对象中的使用
javascript
import QtQuick 2.15
Item {
width: 400
height: 400
Component {
id: dynamicComponent
Rectangle {
property string customText: ""
width: 80
height: 40
color: "lightgreen"
Text {
anchors.centerIn: parent
text: customText
}
Component.onCompleted: {
console.log("动态组件创建完成, ID:", customText);
// 可以在这里进行初始化操作
parent.z = Math.random() * 10;
}
}
}
Timer {
interval: 1000
running: true
repeat: true
triggeredOnStart: true
onTriggered: {
var obj = dynamicComponent.createObject(parent, {
"x": Math.random() * 320,
"y": Math.random() * 360,
"customText": "Obj" + index
});
}
property int index: 0
}
}
二、Component.onDestruction 详解
2.1 基本概念和作用
Component.onDestruction 在组件即将被销毁时触发,用于执行清理操作。
触发时机:
-
当
destroy()方法被调用时 -
父组件被销毁导致子组件被销毁时
-
在 QML 引擎卸载组件时
2.2 基本使用
javascript
import QtQuick 2.15
Item {
width: 400
height: 400
Rectangle {
id: targetRect
width: 150
height: 150
color: "tomato"
anchors.centerIn: parent
// 资源清理
Component.onDestruction: {
console.log("Rectangle 即将被销毁");
console.log("最终位置:", x, y);
console.log("最终颜色:", color);
// 清理可能的内存泄漏
if (timer) {
timer.stop();
timer.destroy();
}
}
// 示例:内部定时器
Timer {
id: timer
interval: 500
repeat: true
running: true
onTriggered: console.log("还在运行...")
}
}
Timer {
interval: 3000
running: true
onTriggered: {
console.log("开始销毁矩形...");
targetRect.destroy();
}
}
Component.onDestruction: {
console.log("根组件即将被销毁");
// 保存应用状态
saveApplicationState();
}
function saveApplicationState() {
// 保存到本地存储
console.log("保存应用状态...");
}
}
2.3 执行顺序
javascript
import QtQuick 2.15
Item {
id: parentItem
Component.onDestruction: console.log("父组件 - 即将销毁")
Item {
id: childItem1
Component.onDestruction: console.log("子组件1 - 即将销毁")
}
Item {
id: childItem2
Component.onDestruction: console.log("子组件2 - 即将销毁")
Rectangle {
id: grandChild
Component.onDestruction: console.log("孙子组件 - 即将销毁")
}
}
Timer {
interval: 1000
running: true
onTriggered: parentItem.destroy()
}
}
// 输出顺序(从最外层到最内层):
// 父组件 - 即将销毁
// 子组件1 - 即将销毁
// 子组件2 - 即将销毁
// 孙子组件 - 即将销毁
三、实际应用场景
3.1 数据初始化和资源加载
javascript
import QtQuick 2.15
import QtQuick.Controls 2.15
ApplicationWindow {
visible: true
width: 800
height: 600
Component.onCompleted: {
console.log("应用程序窗口已启动");
// 1. 初始化数据库连接
initializeDatabase();
// 2. 加载用户配置
loadUserSettings();
// 3. 预加载资源
preloadResources();
// 4. 检查网络连接
checkNetworkConnection();
// 5. 显示启动动画或过渡
showStartupAnimation();
}
Component.onDestruction: {
console.log("应用程序即将关闭");
// 1. 保存用户数据
saveUserData();
// 2. 关闭数据库连接
closeDatabase();
// 3. 清理临时文件
cleanupTempFiles();
// 4. 释放资源
releaseResources();
// 5. 发送关闭统计
sendCloseAnalytics();
}
// 具体实现函数...
function initializeDatabase() {
console.log("初始化数据库...");
}
function saveUserData() {
console.log("保存用户数据...");
}
}
3.2 网络请求管理
javascript
import QtQuick 2.15
import QtQuick.Controls 2.15
Item {
id: networkManager
property var activeRequests: []
function makeRequest(url, callback) {
var request = createRequestObject(url, callback);
activeRequests.push(request);
return request;
}
Component.onDestruction: {
console.log("网络管理器即将销毁,取消所有请求");
// 取消所有进行中的请求
for (var i = 0; i < activeRequests.length; i++) {
var request = activeRequests[i];
if (request && request.abort) {
request.abort();
console.log("已取消请求:", request.url);
}
}
// 清空数组
activeRequests = [];
}
}
3.3 计时器和动画管理
javascript
import QtQuick 2.15
Item {
id: gameEntity
property var activeAnimations: []
property var activeTimers: []
Component.onCompleted: {
console.log("游戏实体已创建");
// 启动游戏逻辑
startGameLogic();
// 开始播放背景音乐
startBackgroundMusic();
}
Component.onDestruction: {
console.log("游戏实体即将销毁");
// 停止所有动画
for (var i = 0; i < activeAnimations.length; i++) {
var animation = activeAnimations[i];
if (animation && animation.stop) {
animation.stop();
}
}
// 停止所有定时器
for (var j = 0; j < activeTimers.length; j++) {
var timer = activeTimers[j];
if (timer && timer.stop) {
timer.stop();
}
}
// 停止音效和音乐
stopAllSounds();
// 保存游戏进度
saveGameProgress();
}
function startGameLogic() {
// 创建游戏逻辑相关的定时器
var timer = Qt.createQmlObject(`
import QtQuick 2.15
Timer {
interval: 16
repeat: true
running: true
onTriggered: updateGameLogic()
}
`, gameEntity);
activeTimers.push(timer);
}
}
四、高级用法和模式
4.1 异步初始化模式
javascript
import QtQuick 2.15
Item {
id: asyncInitializer
signal initializationComplete()
signal initializationFailed(string error)
property bool isInitializing: false
property bool isInitialized: false
Component.onCompleted: {
console.log("开始异步初始化...");
isInitializing = true;
// 使用 Promise 模式处理多个异步任务
performAsyncInitialization();
}
function performAsyncInitialization() {
// 模拟异步初始化序列
Promise.resolve()
.then(() => loadConfiguration())
.then(() => initializeModules())
.then(() => validateState())
.then(() => {
console.log("异步初始化完成");
isInitializing = false;
isInitialized = true;
initializationComplete();
})
.catch((error) => {
console.error("初始化失败:", error);
isInitializing = false;
initializationFailed(error);
});
}
Component.onDestruction: {
if (isInitializing) {
console.warn("组件在初始化过程中被销毁");
cleanupPartialInitialization();
}
}
function cleanupPartialInitialization() {
// 清理部分初始化的资源
console.log("清理部分初始化的资源...");
}
}
4.2 对象池生命周期管理
javascript
import QtQuick 2.15
Item {
id: objectPool
property var objectTemplates: ({})
property var activeObjects: []
property var recycledObjects: []
function registerTemplate(typeName, component) {
objectTemplates[typeName] = {
component: component,
active: [],
recycled: []
};
}
function acquireObject(typeName, properties) {
var template = objectTemplates[typeName];
if (!template) return null;
var obj;
if (template.recycled.length > 0) {
// 从回收池中复用
obj = template.recycled.pop();
console.log("复用对象:", typeName);
} else {
// 创建新对象
obj = template.component.createObject(objectPool, properties);
console.log("创建新对象:", typeName);
// 为对象添加自定义销毁逻辑
obj.Component.onDestruction.connect(function() {
console.log("对象被销毁:", typeName);
removeFromActiveObjects(this);
});
}
// 设置属性并激活
if (properties) {
for (var key in properties) {
obj[key] = properties[key];
}
}
obj.visible = true;
template.active.push(obj);
activeObjects.push(obj);
return obj;
}
function recycleObject(obj) {
obj.visible = false;
// 移动到回收池
// ... 具体逻辑
}
Component.onDestruction: {
console.log("对象池即将销毁,清理所有对象");
// 销毁所有活跃对象
for (var i = activeObjects.length - 1; i >= 0; i--) {
var obj = activeObjects[i];
if (obj && obj.destroy) {
obj.destroy();
}
}
// 清理所有模板
for (var typeName in objectTemplates) {
var template = objectTemplates[typeName];
for (var j = template.recycled.length - 1; j >= 0; j--) {
var recycledObj = template.recycled[j];
if (recycledObj && recycledObj.destroy) {
recycledObj.destroy();
}
}
}
}
}
4.3 错误处理和恢复
javascript
import QtQuick 2.15
Item {
id: resilientComponent
property int initializationAttempts: 0
property int maxAttempts: 3
Component.onCompleted: {
console.log("尝试初始化组件...");
try {
performCriticalInitialization();
console.log("组件初始化成功");
} catch (error) {
console.error("初始化失败:", error);
handleInitializationFailure(error);
}
}
function performCriticalInitialization() {
// 可能抛出异常的操作
initializationAttempts++;
if (Math.random() < 0.3) { // 30% 失败率
throw new Error("模拟初始化失败");
}
// 正常初始化逻辑
console.log("关键初始化步骤完成");
}
function handleInitializationFailure(error) {
if (initializationAttempts < maxAttempts) {
console.log("重试初始化,尝试次数:", initializationAttempts);
// 延迟后重试
retryTimer.start();
} else {
console.error("达到最大重试次数,组件初始化失败");
showErrorState();
}
}
Timer {
id: retryTimer
interval: 1000
onTriggered: performCriticalInitialization()
}
Component.onDestruction: {
console.log("组件即将销毁,当前状态:");
console.log("- 初始化尝试次数:", initializationAttempts);
console.log("- 是否成功:", initializationAttempts > 0);
// 清理重试计时器
if (retryTimer.running) {
retryTimer.stop();
}
}
}
五、最佳实践和注意事项
5.1 最佳实践
-
保持简短 :
onCompleted和onDestruction中的代码应尽量简短 -
错误处理 :在
onCompleted中添加适当的错误处理 -
资源释放 :在
onDestruction中确保释放所有资源 -
避免阻塞 :不要在
onCompleted中执行耗时操作
5.2 常见陷阱
javascript
// 错误示例
Item {
Component.onCompleted: {
// 错误:尝试访问可能还未创建的子元素属性
console.log(childItem.someProperty); // childItem 可能还未准备好
// 错误:执行耗时操作,阻塞UI
performHeavyComputation(); // 会导致界面卡顿
// 错误:创建循环引用
parent.someProperty = this; // 可能导致内存泄漏
}
Component.onDestruction: {
// 错误:访问已被销毁的对象
console.log(parent.width); // parent 可能已被部分销毁
}
}
5.3 调试技巧
javascript
// 添加调试信息
Item {
id: debugComponent
property string componentName: "未命名组件"
Component.onCompleted: {
console.log(`[${componentName}] 组件已创建`);
console.trace(); // 打印调用栈
}
Component.onDestruction: {
console.log(`[${componentName}] 组件将被销毁`);
console.log("存活时间:", Date.now() - creationTime);
}
property int creationTime: Date.now()
}
这些生命周期钩子是 QML 开发中非常重要的工具,正确使用它们可以确保应用的稳定性和良好的性能表现。