最近和Cesium内存泄露杠上了,在Cesuim添加了DataSource后为了修正视角使用了viewer.flyTo(dataSource, {xxx}}方法,结果在销毁cesium时发现Entity无法销毁!

借助万能的Chrome开发工具截取内存信息,发现如下问题:

viewer中某个cancel回调出了问题,在源码中发现其调用发生在使用viewer的flyTo方法或者本身viewer监听的postRender事件反生时。

boundingSphere = BoundingSphere.fromBoundingSpheres(boundingSpheres);

if (!viewer._zoomIsFlight) {
	camera.viewBoundingSphere(boundingSphere, zoomOptions.offset);
	camera.lookAtTransform(Matrix4.IDENTITY);
	clearZoom(viewer);
	zoomPromise.resolve(true);
} else {
	clearZoom(viewer);
	camera.flyToBoundingSphere(boundingSphere, {
		duration : zoomOptions.duration,
		maximumHeight : zoomOptions.maximumHeight,
		complete : function() {
			zoomPromise.resolve(true);
		},
		cancel : function() {
			zoomPromise.resolve(false);
		},
		offset : zoomOptions.offset
	});
}

而这里最重要的是我们只要调用了flyTo方法,viewer._zoomIsFlight就会被置成true,后续viewer的所有postRender事件都会走else流程。

开始我们怀疑是不是在进行viewer销毁时因为触发了scene的 postRender 事件而这时我们viewer对应的dom节点已经被销毁导致cancel出问题。所以在flyTo(xxx).then()中强制把 _zoomIsFlight 置为false。结果内存泄露点还是在cancel这里。

所以猜测内存泄露并不是发生在销毁阶段,修改源代码else流程中打印信息,果然调用流程只反生在flyTo阶段!!!为了确认不是项目其他代码影响了结果,直接从官网demo中提取最简单的添加 entity->flyTo(entity)->remove后销毁viewer,内存泄露依旧。

所以应该是Cesium自身就存在这个问题,没有办法项目中所有涉及flyTo的方法暂时改为zoomTo解决。