-
Creator 版本: 3.4.2
-
目标平台: Google
-
重现方式:在场景中新建一个节点并隐藏,挂上一个会在onLoad,onDestroy生命周期中打印内容的组件。运行项目后销毁该节点即可复现。
这。。算是BUG么?还是就是这样设计的?。。我现在是通过子节点来管理部分资源,如果节点被销毁时子节点还没显示过。。那我这部分资源就等于泄漏了。
Creator 版本: 3.4.2
目标平台: Google
重现方式:在场景中新建一个节点并隐藏,挂上一个会在onLoad,onDestroy生命周期中打印内容的组件。运行项目后销毁该节点即可复现。
这。。算是BUG么?还是就是这样设计的?。。我现在是通过子节点来管理部分资源,如果节点被销毁时子节点还没显示过。。那我这部分资源就等于泄漏了。
这个不是bug 一直都是这样 没生成怎么会销毁呢
看了一下引擎层,确实是这样设计的 onLoad回调没走完 就不会进

你可以用_onPreDestroy来监听销毁逻辑 不过我不知道会有什么问题
确实。。翻到一篇18年的帖子。。那时候就是这样的了。既然如此还是自己管理下好了。
感谢大佬 但感觉不稳妥 还是算了。
把逻辑(业务)和表现分离,要管理资源的话节点就应该激活。表现的部分单独放一个节点控制显示和隐藏。
我觉得有2种,
1.先加载资源,再创建UI, 优点是没有异步等问题,缺点是首次显示对象出现比较慢
2. 同时创建UI和加载资源,优点是“多线程”速度快,缺点是资源异步加载完毕后,由于逻辑或用户行为导致UI可能已经关闭或已经被destroy掉了,需要各种判空等,管理起来复杂,
所以我倾向于做一个加载资源过渡UI,再创建显示对象
感谢回复 应该还是我的思路问题。问这个问题时我的使用场景其实是这样的:节点A上挂了个自己实现的Sprite组件,本意是通过这个组件来管理图片资源的引用计数问题,预期中释放资源的方式之一就是通过监听onDestroy,然而出现了上面说的onDestroy未触发的情况。
提前加载图片资源不适用于部分场景(比如不确定要展示的图片 或者单次展示的图片数量是有限的)所以会将加载操作放在具体的子节点下面。将该加载操作分离出去感觉上稍嫌麻烦,比如等资源加载完之后如何优雅通知该子节点。
现在看来其实自己实现一个方法,在destroy节点前调用,自己管理各个节点和组件做销毁前准备是比较合适的。onDestroy方法稍显鸡肋,如果onDestroy带个回参表示自己有没有经历过onLoad,不知这样合不合适。
这种情况下目前 onLoad/onDestroy 的成对调用,更不容易出问题不是吗?否则 onLoad 引用计数 +1,没调用 onLoad,反而 onDestroy 执行了 -1
感谢回复,emm。。那个。。我的addRef其实不是在onLoad执行的 是在setData。而setData和生命周期没关系。。
资源的加载是由一个专门的管理类进行的,这个管理类不关心使用者到底怎么使用,只要用了我就addRef,所以我前面期待“子节点通过onDestroy来自己调用管理类去decRef”其实就不太可能了。因为onLoad和onDestroy是挂钩的,而我希望的其实是一个和生命周期关系不大,只要组件被销毁了就会调用的方法。
这里对onLoad和onDestroy挂钩没什么意见,是我一开始对onDestroy理解不足。期待通过onDestroy来管理资源其实也有点偷懒的想法,因为这样就不用关心到底谁用了资源。还是老老实实做资源管理好了。。
这个需求挺合理
这个方法实现不了比较通用的组件,对使用者要求太高。自己内部项目是可以。
或许引擎需要支持一个能够永远触发的 onDestroy 才行,否则涉及到被动初始化的组件(如通过 setter、API),将无法追踪生命周期的结束。
或者,被动初始化时,组件能够调用自身的 onLoad(),然后就可以确保 onDestroy 会被执行到。
确实不会很通用。。使用的时候得按规范来。
引擎这边能提供永远触发的onDestroy当然是最好的。对我这种“希望由具体子节点来通知增加或减少引用”的需求而言,体验是很好的。
至于被动初始化时组件自调用onLoad。。。不知道好不好,说不定到时候又会有人发帖子“组件明明没有添加到场景中,怎么自己onLoad了?”之类的问题。也许我需要的是一个新方法,而不是重新设计onLoad和onDestroy的关系和触发方式。毕竟我的需求跟生命周期关系不大甚至无关。 
引擎组这边如果不好解决的话,还是将时间花在其它地方吧。这里的体验提升有限,而且开发者也可以根据自己的框架设计下。请继续提升性能吧~
不是的,如果addRef是在setDate中添加的,那么应该在"removeData"中调用decRef,这种成对调用才是合理的
也没错 希望之后评论的各位不要太纠结“成对调用”。我对成对调用没有意见,我的代码里面确实也有个“removeData”。我希望的其实是一个“只要组件被销毁就会响应”的方法,而我一开始以为onDestroy就是这样的方法。如果有这样的方法,我(指具体子节点)就可以自己调用removeData,而不用通过上级来调用。这是一种偷懒取巧的做法,只是我偷懒失败了而已。 
我的意思是让用户自己调用 onLoad
比如
set parent () {
this._parent = xxx;
ths.ensureLoad(); // 此时引擎识别出来,并且会帮助用户自动调用 onDestroy()
}
啊。。其实我想表达的是生命周期可能会更难以理解的情况。。举例中用到的ensureLoad方法,调用后到底会发生什么呢?
1)如果onLoad没执行,那该方法会执行一次onLoad;如果执行过,那该方法不做任何事情。
2)设置一个新变量,onDestroy的时候会额外判断这个新变量,如果新变量符合条件,则允许执行onDestroy
情况1要求开发谨慎使用ensureLoad方法,情况2感觉影响较小,但这等于和onLoad又脱钩了。从之前的聊天中我觉得是指情况1。
为啥我说要谨慎使用?(请原谅我不了解实现。。也没去翻源码证明下面的猜想是不是合理的)onLoad的描述是这样的
感觉ensureLoad的出现会使得onLoad和生命周期脱离了关系,更像“init”方法了。生命周期有它的局限性,但我觉得这局限性是好的。
感谢jare大佬对这个问题的关注~但我想要的只是个一个"onDestroy"而已。 
从之前的聊天中我觉得是指情况1。
是的。
要执行,对其他引擎逻辑没影响,但是要求这个组件自身的初始化逻辑足够独立。如果 onLoad 依赖第三方,显然不是随时都能调用的。
其实 ensureLoad 只是一个手段,目的是允许组件自定义如何初始化,方法不止这一个。
今天 onDestroy 遇到的问题,等于 “如果我的onDestroy希望是在“场景中且自己和自己的上级节点都未激活的”情况下被调用的,但我又有ensureDestroy的需求”。
这是问题的转移,用户需求肯定无法完全满足,只能向用户暴露问题以及对策,选择权交给用户。
从我们引擎组件的编写经验来说,这样的 ensureLoad 确实是有价值的,至少对内有价值
ensureLoad 相当于一个强制 Transition,把 Any 状态合法过渡到已初始化状态
但我想要的只是个一个"onDestroy"而已
本质上问题是如何在破坏 API 兼容性(打破 onDestroy 和 onLoad 绑定),跟不打破但支持显式调用 onLoad 之间做取舍。从政治正确的角度我们首先想的肯定是后者的方案。如果不怕老用户发飙,我可以 YY 一下,粗暴地改造引擎如下:
感谢反馈。