HarmonyOS鸿蒙Next中【高德地图】动态绘制大量marker耦合问题、性能优化初步解决方案(使用MapKit也可参考)
HarmonyOS鸿蒙Next中【高德地图】动态绘制大量marker耦合问题、性能优化初步解决方案(使用MapKit也可参考) 对于地图功能丰富的项目,有绘制不同样式Marker的需求,而且很多时候不是固定图标,而是需要动态绘制。
目前能找到的办法就是通过componentSnapshot截图来实现动态绘制Marker,
然而componentSnapshot不支持全局builder,很多小伙伴初步接触鸿蒙,只能把绘制Marker的builder方法放到业务组件或者页面中,
这样增加了代码的耦合性,还无法复用。
这时可以尝试这样的思路:
写一个mapController类管理地图,生成marker的时候,用外部传入的一个builder方法。这个buider方法需要在某个组件实现并传入,实现builder的时候还可以直接调用单独封装的自定义组件。
// MapController:
stationMarkerBuilder?: (station:MapStationListBean) => void
...
let pixmap = await componentSnapshot.createFromBuilder(()=>{if (this.stationMarkerBuilder)this.stationMarkerBuilder(item)})
// MapPage:
this.mapController.stationMarkerBuilder =
(station) => { this.stationBuilder(station) }
...
@Builder
stationBuilder(station:MapStationListBean) {
MapStationMarkerView({num:station.stationNum})
}
耦合的问题解决了。但实际调试我们还会发现,这样实时的绘制,在Marker比较多的情况下,性能很差。
每次绘制要300-500ms,当动态内容很多,每次绘制几十上百个marker,顺序绘制的话要好几秒,效果很差劲。
这时可以尝试将异步并发绘制,再更进一步将代码拆分,
在上面代码的基础上,把单独封装marker对象,把业务数据、marker配置、builder方法都放进去,生成的图片也存在这里,这样有更多优化空间。
export class LineMapStationMarkerObj {
stationBean:MapStationListBean
option?:MarkerOptions
icon?:BitmapDescriptor
stationMarkerBuilder?: (station:MapStationListBean) => void
constructor(station:MapStationListBean) {
this.stationBean = station
}
async updateOption() {
let latitude = Number(this.stationBean.latitude)
let longitude = Number(this.stationBean.longitude)
if (latitude && longitude) {
let option: MarkerOptions = new MarkerOptions();
if (!this.icon) {
console.time('componentSnapshotStation')
let pixmap = await componentSnapshot.createFromBuilder(() => {
if (this.stationMarkerBuilder) this.stationMarkerBuilder(this.stationBean)
}) //, 320, true, {scale : 2, waitUntilRenderFinished : true})
console.timeEnd('componentSnapshotStation')
//
this.icon = BitmapDescriptorFactory.fromPixelMapSync(pixmap)
}
if (this.icon) {
option.setIcon(this.icon);
}
option.setDraggable(false);
option.setPosition(new LatLng(latitude, longitude));
option.setAnchor(0.5, 1);
this.option = option
}
}
}
// MapController:
// 重新绘制站点marker
async redrawStationMarkers(data:MapStationListBean[]) {
this.stationList = data
if (!this.aMap) {
return
}
// 清除之前的
this.stationMarkers?.forEach((marker)=>{
this.aMap?.removeOverlay(marker.getId())
})
// 整理数据、marker设置
let stationMarkerObjs : LineMapStationMarkerObj[] = []
let promiseList : Promise<void>[] = [] // 异步任务
data.forEach((item) => {
let markerObj = new LineMapStationMarkerObj(item)
markerObj.stationMarkerBuilder = this.stationMarkerBuilder
stationMarkerObjs.push(markerObj)
// 添加异步任务
promiseList.push(markerObj.updateOption())
})
this.stationMarkerObjs = stationMarkerObjs
// 并发异步获取option
Promise.all(promiseList).then(()=>{
let optionsList :ArrayList<MarkerOptions> = new ArrayList<MarkerOptions>()
this.stationMarkerObjs?.forEach((markerObj) => {
optionsList.add(markerObj.option)
})
this.stationMarkers = this.aMap?.addMarkers(optionsList)
})
}
优化到这一步,效果还可以接受~
如果小伙伴们有更好、更进一步的方案,欢迎评论分享~
更多关于HarmonyOS鸿蒙Next中【高德地图】动态绘制大量marker耦合问题、性能优化初步解决方案(使用MapKit也可参考)的实战教程也可以访问 https://www.itying.com/category-93-b0.html
更多关于HarmonyOS鸿蒙Next中【高德地图】动态绘制大量marker耦合问题、性能优化初步解决方案(使用MapKit也可参考)的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html
在HarmonyOS鸿蒙Next中,动态绘制大量marker时,可能会遇到性能瓶颈和耦合问题。初步解决方案包括:
- 批量绘制:使用
MarkerOptions
批量添加marker,减少频繁调用导致的性能损耗。 - 对象池复用:通过对象池管理marker,避免频繁创建和销毁对象,提升性能。
- 异步处理:将marker的绘制操作放在子线程中执行,避免阻塞主线程。
- 数据分页:按需加载marker数据,减少一次性绘制过多marker的压力。
- 简化UI:优化marker的图标和动画,减少渲染复杂度。
这些方法同样适用于使用MapKit的场景,能有效提升性能并降低耦合度。