1200字范文,内容丰富有趣,写作的好帮手!
1200字范文 > 解决百度地图内存泄露问题

解决百度地图内存泄露问题

时间:2021-07-23 14:54:46

相关推荐

解决百度地图内存泄露问题

百度地图内存泄露问题

百度地图中,我们会遇到循环创建marker点时内存占用不停上涨导致页面直接崩掉。或者数据量过大页面渲染CPU占用过高导致页面卡死。

如图:

需求实例:

使用百度地图展示车辆的位置,并且30s刷新一次位置信息。

面对这样的需要,展示车辆的位置,每一个车辆需要一个Marker点,车辆太对需要考虑聚合,

代码实现如下:

const clustererInstance = null;const mapInstance = null;// 初始化地图...// 创建Marker点function addMarker(data) {// 创建之前先清除地图上的覆盖物mapInstance.clearOverlays();const markers = [];for (let i = 0, len = data.length; i < len; i++) {const item = data[i];const point = new BMap.Point(item.long, item.lat);const marker = new BMap.Marker(point);markers.push(marker);}if (clustererInstance) {clustererInstance.clearMarkers();clustererInstance.addMarkers(totalMarkers);} else {clustererInstance = new BMapLib.MarkerClusterer(mapInstance, { markers: markers });}}

这里只是实现创建marker点,定时器和数据请求就不展示了。在每次循环请求数据回来都调用一次addMarker方法,可以完成车辆点的展示。

问题一:数据量小时,这样的实现不会出现明显的问题,但是当数据量达到几万次,或者更大时,页面在循环创建Marker点时,虽然每次都使用clearOverlays,和clearMarkers进行了清除,但是百度的这两个方法并没有实现内存释放。导致每次循环浏览器的内存都在不断增加,直到页面崩掉。

解决办法:

当面对这个问题时,我们在第一次循环创建marker点时借助vue的store将其存储起来,下一次循环时只是修改marker的postion即可。代码如下:

import { mapState } from 'vuex';const clustererInstance = null;const mapInstance = null;computed: {...mapState(['allMcMarkers'])},methods: {// 初始化地图initMap() {...},// 创建Marker点addMarker(data) {// 创建之前先清除地图上的覆盖物mapInstance.clearOverlays();const markers = [];for (let i = 0, len = data.length; i < len; i++) {const item = data[i];const marker = null;const point = new BMap.Point(item.long, item.lat);// 判断是否存在marker点,有则直接替换位置if (this.allMcMarkers[i]) {marker = this.allMcMarkers[i];marker.setPosition(point);} else {marker = new BMap.Marker(point);this.allMcMarkers.push(marker);}markers.push(marker);}if (clustererInstance) {clustererInstance.clearMarkers();clustererInstance.addMarkers(totalMarkers);} else {clustererInstance = new BMapLib.MarkerClusterer(mapInstance, { markers: markers });}}}

问题二:

当数据量过大时,前端页面渲染内存占用会很大。也会导致页面卡死。所以我们可以考虑分批渲染。分批渲染可以使用setInterval或setTimeout、requestAnimationFrame来实现。

setTimeout实现分批渲染

import { mapState } from 'vuex';const clustererInstance = null;const mapInstance = null;computed: {...mapState(['allMcMarkers'])},methods: {// 数据分组 每组5000条数据group (data) {var result = [];const _l = Math.ceil(data.length / 5000);for (var i = 0; i < _l; i++) {result.push(data.slice(i * 5000, (i + 1) * 5000));}return result;},batchRender (data) {return new Promise((resolve, reject) => {var groups = this.group(data);let totalMarkers = [];const that = this;this.renderMarkersLoading = true;const zoom = 5;for (let i = 0; i < groups.length; i++) {// 闭包, 保持i值的正确性// eslint-disable-next-line wrap-iifewindow.setTimeout(function () {var group = groups[i];var index = i;return function () {// 分批渲染totalMarkers = totalMarkers.concat(that.addMarker(group, zoom, index));if (totalMarkers.length === data.length) {that.createMarker(totalMarkers);that.renderMarkersLoading = false;}};}(), 1);}resolve();});},// 创建Marker点addMarker(data) {// 创建之前先清除地图上的覆盖物mapInstance.clearOverlays();const markers = [];for (let i = 0, len = data.length; i < len; i++) {const item = data[i];const marker = null;const point = new BMap.Point(item.long, item.lat);// 判断是否存在marker点,有则直接替换位置if (this.allMcMarkers[i]) {marker = this.allMcMarkers[i];marker.setPosition(point);} else {marker = new BMap.Marker(point);this.allMcMarkers.push(marker);}markers.push(marker);}return markers;},createMarker (totalMarkers) {if (totalMarkers.length) {if (clustererInstance) {clustererInstance.clearMarkers();clustererInstance.addMarkers(totalMarkers);} else {clustererInstance = new BMapLib.MarkerClusterer(this.map, { markers: totalMarkers });}}},}

同样在实现动画的渲染时我们最优选择requestAnimationFrame实现分批渲染。

上述解决办法可能不是最优的,如果你有更好的解决办法,欢迎留言。

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。