[6.5.0][Fix]解决偶现卡片数量不足的问题

This commit is contained in:
chenfufeng
2024-07-24 20:37:54 +08:00
parent da2a9a9add
commit 2c86d8ef6b
2 changed files with 186 additions and 121 deletions

View File

@@ -18,6 +18,7 @@ import com.mogo.eagle.core.data.config.FunctionBuildConfig
import com.mogo.eagle.core.data.road.RoadCameraLive
import com.mogo.eagle.core.function.business.roadcross.net.BATCH_LIVE
import com.mogo.eagle.core.function.business.roadcross.net.INDERoadCameraApiService
import com.mogo.eagle.core.function.business.travelreality.view.VideoMarkerEntity
import com.mogo.eagle.core.function.call.autopilot.CallerChassisLocationWGS84ListenerManager
import com.mogo.eagle.core.function.call.map.CallerMapUIServiceManager
import com.mogo.eagle.core.network.MoGoRetrofitFactory
@@ -235,10 +236,10 @@ class TravelRealityModel private constructor() {
fun downloadImage(
context: Context, url: String?,
latLng: LatLng,
videoMarkerList: MutableList<VideoMarkerEntity>,
lineId: Long,
onSuccess: ((Bitmap, LatLng, Long) -> Unit),
onFailed: ((LatLng, Long) -> Unit)
onSuccess: ((Bitmap, MutableList<VideoMarkerEntity>, Long) -> Unit),
onFailed: ((MutableList<VideoMarkerEntity>, Long) -> Unit)
) {
if (url.isNullOrEmpty()) return
val radiusPx = AutoSizeUtils.dp2px(context, 24f).toFloat()
@@ -250,14 +251,14 @@ class TravelRealityModel private constructor() {
.load(url)
.into(object : CustomTarget<Bitmap>() {
override fun onResourceReady(resource: Bitmap, transition: Transition<in Bitmap>?) {
onSuccess(resource, latLng, lineId)
onSuccess(resource, videoMarkerList, lineId)
}
override fun onLoadCleared(placeholder: Drawable?) {}
override fun onLoadFailed(errorDrawable: Drawable?) {
super.onLoadFailed(errorDrawable)
onFailed(latLng, lineId)
onFailed(videoMarkerList, lineId)
}
})
}

View File

@@ -188,7 +188,7 @@ class TravelRealityView @JvmOverloads constructor(
* 在轨迹点附近的路口设备
*/
@Volatile
private var deviceInPathList: List<CrossDeviceBean>? = null
private var deviceInPathList: List<DeviceInfoBean>?? = null
@Volatile
private var roadTrackList: List<List<List<Double>?>?>? = null
@@ -502,9 +502,9 @@ class TravelRealityView @JvmOverloads constructor(
if (eventList.isEmpty()) {
listener?.onDraw(emptyList(), true)
// 没有事件则全部用路口设备补齐
retryGetCrossDevice(ArrayList<String>(), HashMap<String, VideoMarkerEntity>())
retryGetCrossDevice(HashMap(), 0)
// 清除道路事件
drawMarkers(DRAW_ROAD_EVENT, ArrayList<MarkerOptions>())
drawMarkers(DRAW_ROAD_EVENT, ArrayList())
} else {
val eventDrawMap = HashMap<String, EventDrawBean>()
val eventOptionsList = ArrayList<MarkerOptions>()
@@ -550,59 +550,75 @@ class TravelRealityView @JvmOverloads constructor(
}
private fun completeQuantity(roadEvents: ArrayList<EventBean>) {
val ipPointEntityMap = HashMap<String, VideoMarkerEntity>()
val ipPointEntityMap = HashMap<String, MutableList<VideoMarkerEntity>>()
// 全部展示事件,事件数不足则用路口设备补齐
Log.d(TAG, "已绘制的道路事件个数为:${roadEvents.size}")
if (roadEvents.size >= 3) {
val ipList = mutableListOf<String>()
roadEvents[0].let {
it.ip?.also { ip ->
if (ip.isEmpty()) return@also
ipPointEntityMap[ip] = VideoMarkerEntity(
coordinateConverterWgsToGcj(it.lat, it.lon),
it.title,
it.orientation
if (!ipPointEntityMap.containsKey(ip)) {
ipPointEntityMap[ip] = ArrayList()
}
ipPointEntityMap[ip]?.add(
VideoMarkerEntity(
coordinateConverterWgsToGcj(it.lat, it.lon),
it.title,
it.orientation
)
)
ipList.add(ip)
}
}
roadEvents[(roadEvents.size - 1) / 2].let {
it.ip?.also { ip ->
if (ip.isEmpty()) return@also
ipPointEntityMap[ip] = VideoMarkerEntity(
coordinateConverterWgsToGcj(it.lat, it.lon),
it.title,
it.orientation
if (!ipPointEntityMap.containsKey(ip)) {
ipPointEntityMap[ip] = ArrayList()
}
ipPointEntityMap[ip]?.add(
VideoMarkerEntity(
coordinateConverterWgsToGcj(it.lat, it.lon),
it.title,
it.orientation
)
)
ipList.add(ip)
}
}
roadEvents[roadEvents.size - 1].let {
it.ip?.also { ip ->
if (ip.isEmpty()) return@also
ipPointEntityMap[ip] = VideoMarkerEntity(
coordinateConverterWgsToGcj(it.lat, it.lon),
it.title,
it.orientation
if (!ipPointEntityMap.containsKey(ip)) {
ipPointEntityMap[ip] = ArrayList()
}
ipPointEntityMap[ip]?.add(
VideoMarkerEntity(
coordinateConverterWgsToGcj(it.lat, it.lon),
it.title,
it.orientation
)
)
ipList.add(ip)
}
}
reqCrossLive(ipList, ipPointEntityMap)
reqCrossLive(ipPointEntityMap)
} else {
val ipList = mutableListOf<String>()
var count = 0
roadEvents.forEach {
it.ip?.let { ip ->
if (ip.isEmpty()) return@let
ipPointEntityMap[ip] = VideoMarkerEntity(
coordinateConverterWgsToGcj(it.lat, it.lon),
it.title,
it.orientation
count++
if (!ipPointEntityMap.containsKey(ip)) {
ipPointEntityMap[ip] = ArrayList()
}
ipPointEntityMap[ip]?.add(
VideoMarkerEntity(
coordinateConverterWgsToGcj(it.lat, it.lon),
it.title,
it.orientation
)
)
ipList.add(ip)
}
}
retryGetCrossDevice(ipList, ipPointEntityMap)
retryGetCrossDevice(ipPointEntityMap, count)
}
}
@@ -680,8 +696,8 @@ class TravelRealityView @JvmOverloads constructor(
* handleCrossDevices -> 计算Marker方向 -> 缓存deviceInPathList
*/
private fun retryGetCrossDevice(
ipList: MutableList<String>,
ipPointEntityMap: HashMap<String, VideoMarkerEntity>
ipPointEntityMap: HashMap<String, MutableList<VideoMarkerEntity>>,
eventSize: Int
) {
Log.d(TAG, "retryGetCrossDevice")
val crossDeviceListTmp = deviceInPathList
@@ -690,71 +706,109 @@ class TravelRealityView @JvmOverloads constructor(
Log.d(TAG, "尝试多次后仍无法获取到路口设备数据!")
break
}
Thread.sleep(150)
Thread.sleep(250)
retryCount++
}
var maxSize = 3 - ipList.size
var maxSize = 3 - eventSize
if (maxSize <= 0) {
Log.d(TAG, "全息路口个数计算有误则返回!")
return
}
Log.d(TAG, "待查询的事件个数为:${ipList.size}")
Log.d(TAG, "待查询缩略图的事件个数为:${eventSize}")
if (!crossDeviceListTmp.isNullOrEmpty()) {
Log.d(TAG, "缓存的全息路口个数为:${crossDeviceListTmp.size}")
// 轨迹线附近的路口设备取几个进行卡片展示
for (i in crossDeviceListTmp.indices) {
if (maxSize > 0 && !crossDeviceListTmp[i].deviceInfoList.isNullOrEmpty()) {
crossDeviceListTmp[i].deviceInfoList!![0].deviceIp?.let {
ipPointEntityMap[it] = VideoMarkerEntity(
coordinateConverterWgsToGcj(
crossDeviceListTmp[i].deviceInfoList!![0].lat,
crossDeviceListTmp[i].deviceInfoList!![0].lon
), "全息路口", crossDeviceListTmp[i].deviceInfoList!![0].orientation
crossDeviceListTmp.forEach { deviceInfoBean ->
if (maxSize > 0) {
deviceInfoBean.deviceIp?.let {
if (!ipPointEntityMap.containsKey(it)) {
ipPointEntityMap[it] = ArrayList()
}
ipPointEntityMap[it]?.add(
VideoMarkerEntity(
coordinateConverterWgsToGcj(
deviceInfoBean.lat,
deviceInfoBean.lon
),
"全息路口",
deviceInfoBean.orientation
)
)
ipList.add(it)
maxSize--
}
}
}
}
reqCrossLive(ipList, ipPointEntityMap)
reqCrossLive(ipPointEntityMap)
}
/**
* 先下载图片然后设置给View
* 再转换成BitmapDescriptor最后进行渲染
* 1_ip -> 1_url -> n_bitmap(标题不同需生成n个) -> n_marker
*/
private fun downloadImage(url: String, latLng: LatLng?, title: String?, orientation: Int = 0) {
if (latLng == null || url.isEmpty()) return
private fun downloadImage(url: String, videoList: MutableList<VideoMarkerEntity>) {
if (videoList.isEmpty() || url.isEmpty()) return
travelNetWorkModel.downloadImage(
context,
url,
latLng,
videoList,
CallerAutoPilotStatusListenerManager.getLineId(),
onSuccess = { bitmap, latLng, lineId ->
if (CallerAutoPilotStatusListenerManager.getLineId() != 0L) {
val view = EventVideoView(context, title = title, orientation = orientation)
onSuccess = { bitmap, videoMarkerList, lineId ->
// if (CallerAutoPilotStatusListenerManager.getLineId() != 0L) {
val optionList = ArrayList<MarkerOptions>()
var view: EventVideoView
videoMarkerList.forEach { videoEntity ->
view = EventVideoView(
context,
title = videoEntity.title,
orientation = videoEntity.orientation
)
view.setBitmap(bitmap)
updateVideoMarker(view, latLng)
} else {
Log.w(TAG, "downloadImage:onSuccess:lineId为0!")
optionList.add(MarkerOptions().also {
it.position(videoEntity.latLng)
it.icon(BitmapDescriptorFactory.fromView(view))
})
}
updateVideoMarker(optionList)
// } else {
// Log.w(TAG, "downloadImage:onSuccess:lineId为0!")
// }
},
onFailed = { latLng, lineId ->
if (CallerAutoPilotStatusListenerManager.getLineId() != 0L) {
val view = EventVideoView(context, title = title, orientation = orientation)
onFailed = { videoMarkerList, lineId ->
// if (CallerAutoPilotStatusListenerManager.getLineId() != 0L) {
val optionList = ArrayList<MarkerOptions>()
var view: EventVideoView
videoMarkerList.forEach { videoEntity ->
view = EventVideoView(
context,
title = videoEntity.title,
orientation = videoEntity.orientation
)
view.setPlaceHolder()
updateVideoMarker(view, latLng)
} else {
Log.w(TAG, "downloadImage:onFailed:lineId为0!")
optionList.add(MarkerOptions().also {
it.position(videoEntity.latLng)
it.icon(BitmapDescriptorFactory.fromView(view))
})
}
updateVideoMarker(optionList)
// } else {
// Log.w(TAG, "downloadImage:onFailed:lineId为0!")
// }
})
}
private fun reqCrossLive(
ipList: MutableList<String>,
ipPointEntityMap: HashMap<String, VideoMarkerEntity>
ipPointEntityMap: HashMap<String, MutableList<VideoMarkerEntity>>
) {
val ipList = ipPointEntityMap.keys.toMutableList()
Log.d(TAG, "请求获取缩略图,个数为:${ipList.size}!")
if (ipList.isEmpty()) {
return
}
travelNetWorkModel.batchRequestCrossLive(ipList, onSuccess = {
Log.d(TAG, "Cross live result is:$it")
val liveOptionsList = ArrayList<MarkerOptions>()
@@ -764,64 +818,71 @@ class TravelRealityView @JvmOverloads constructor(
it.forEach { roadCamera ->
roadCamera.ip?.let { ip ->
markerOption = MarkerOptions()
markerOption.zIndex(0.9f)
if (roadCamera.imageUrl.isNullOrEmpty()) {
var view: EventVideoView
if (ipPointEntityMap[ip] != null) {
// 计算卡片四个顶点的高德地图经纬度
ipPointEntityMap[ip]?.latLng?.let { pos ->
// 一个ip可能对应多个卡片缩略图
ipPointEntityMap[ip]!!.forEach { videoMarkerEntity ->
// 计算卡片四个顶点的高德地图经纬度
vertexList.addAll(
getRectVertex(
ipPointEntityMap[ip]!!.orientation,
pos
videoMarkerEntity.orientation,
videoMarkerEntity.latLng
)
)
markerOption = MarkerOptions()
markerOption.zIndex(0.9f)
markerOption.position(videoMarkerEntity.latLng)
view = EventVideoView(
context,
title = videoMarkerEntity.title,
orientation = videoMarkerEntity.orientation
)
pair =
travelNetWorkModel.calculateAnchor(videoMarkerEntity.orientation)
Log.d(
TAG,
"绘制时位置为:${videoMarkerEntity.latLng},标题为:${videoMarkerEntity.title},方向为:${videoMarkerEntity.orientation},锚点为:${pair}"
)
markerOption.anchor(pair.first, pair.second)
view.setPlaceHolder()
markerOption.icon(BitmapDescriptorFactory.fromView(view))
liveOptionsList.add(markerOption)
}
markerOption.position(ipPointEntityMap[ip]?.latLng)
view = EventVideoView(
context,
title = ipPointEntityMap[ip]!!.title,
orientation = ipPointEntityMap[ip]!!.orientation
)
pair =
travelNetWorkModel.calculateAnchor(ipPointEntityMap[ip]!!.orientation)
Log.d(
TAG,
"绘制时位置为:${ipPointEntityMap[ip]?.latLng},标题为:${ipPointEntityMap[ip]!!.title},方向为:${ipPointEntityMap[ip]!!.orientation},锚点为:${pair}"
)
markerOption.anchor(pair.first, pair.second)
view.setPlaceHolder()
markerOption.icon(BitmapDescriptorFactory.fromView(view))
} else {
Log.d(TAG, "缓存中未查到对应ip")
Log.d(TAG, "缓存中未查到对应ip!")
return@let
}
} else {
// 需要下载缩略图
markerOption.icon(null)
// 计算卡片四个顶点的高德地图经纬度
ipPointEntityMap[ip]?.latLng?.let { pos ->
vertexList.addAll(
getRectVertex(
ipPointEntityMap[ip]?.orientation ?: 0,
pos
if (ipPointEntityMap[ip] != null) {
ipPointEntityMap[ip]!!.forEach { videoMarkerEntity ->
// 计算卡片四个顶点的高德地图经纬度
vertexList.addAll(
getRectVertex(
videoMarkerEntity.orientation,
videoMarkerEntity.latLng
)
)
// 需要下载缩略图
markerOption = MarkerOptions()
markerOption.zIndex(0.9f)
markerOption.icon(null)
markerOption.position(videoMarkerEntity.latLng)
pair = travelNetWorkModel.calculateAnchor(
videoMarkerEntity.orientation
)
markerOption.anchor(pair.first, pair.second)
liveOptionsList.add(markerOption)
}
downloadImage(
roadCamera.imageUrl!!,
ipPointEntityMap[ip]!!
)
} else {
Log.d(TAG, "缓存中未查到对应ip!!")
return@let
}
markerOption.position(ipPointEntityMap[ip]?.latLng)
pair = travelNetWorkModel.calculateAnchor(
ipPointEntityMap[ip]?.orientation ?: 0
)
markerOption.anchor(pair.first, pair.second)
downloadImage(
roadCamera.imageUrl!!,
ipPointEntityMap[ip]?.latLng,
ipPointEntityMap[ip]?.title,
ipPointEntityMap[ip]?.orientation ?: 0
)
}
liveOptionsList.add(markerOption)
}
}
Log.d(TAG, "绘制卡片的个数为:${liveOptionsList.size}")
@@ -833,7 +894,10 @@ class TravelRealityView @JvmOverloads constructor(
})
}
private fun handleCrossDevices(crossDeviceList: List<CrossDeviceBean>, globalList: ArrayList<Point>?) {
private fun handleCrossDevices(
crossDeviceList: List<CrossDeviceBean>,
globalList: ArrayList<Point>?
) {
if (crossDeviceList.isEmpty()) return
val crossOptionsList = ArrayList<MarkerOptions>()
var distance = 0.0
@@ -870,7 +934,10 @@ class TravelRealityView @JvmOverloads constructor(
globalList[index + 1].lon,
globalList[index + 1].lat
)
deviceInPaths.add(deviceBean)
// 深拷贝一下数据
deviceInPaths.add(DeviceInfoBean(deviceBean.deviceIp, deviceBean.lon, deviceBean.lat).also { deviceInfo ->
deviceInfo.orientation = deviceBean.orientation
})
crossOptionsList.add(MarkerOptions().apply {
position(
coordinateConverterWgsToGcj(
@@ -891,7 +958,7 @@ class TravelRealityView @JvmOverloads constructor(
false
)
}
deviceInPathList = arrayListOf(CrossDeviceBean("", 0.0, "", 0.0, deviceInPaths))
deviceInPathList = deviceInPaths
Log.d(TAG, "待绘制的全息路口的个数为:${crossOptionsList.size}")
// 绘制路口设备
drawMarkers(DRAW_CROSS_DEVICE, crossOptionsList)
@@ -1106,12 +1173,7 @@ class TravelRealityView @JvmOverloads constructor(
}
}
private fun updateVideoMarker(view: EventVideoView, latLng: LatLng?) {
if (latLng == null) return
val options = MarkerOptions()
options.position(latLng)
options.icon(BitmapDescriptorFactory.fromView(view))
Log.d(TAG, "更新时位置为:${latLng},标题为:${view.title}")
private fun updateVideoMarker(options: List<MarkerOptions>) {
Message.obtain().apply {
what = UPDATE_VIDEO_MARKER
obj = options
@@ -1380,7 +1442,7 @@ class TravelRealityView @JvmOverloads constructor(
UPDATE_VIDEO_MARKER -> {
removeMessages(UPDATE_VIDEO_MARKER)
if (isMapDestroyed) return
realUpdateVideoMarker(msg.obj as MarkerOptions)
realUpdateVideoMarker(msg.obj as List<MarkerOptions>)
}
CLEAR_ALL_DATA -> {
@@ -1554,11 +1616,13 @@ class TravelRealityView @JvmOverloads constructor(
liveMarkerList.clear()
}
private fun realUpdateVideoMarker(options: MarkerOptions) {
private fun realUpdateVideoMarker(options: List<MarkerOptions>) {
Log.d(TAG, "realUpdateVideoMarker")
liveMarkerList.forEach {
if (it.position == options.position) {
it.setIcon(options.icon)
liveMarkerList.forEach { liveMarker ->
options.forEach {
if (it.position == liveMarker.position) {
liveMarker.setIcon(it.icon)
}
}
}
}