Android Studio 如何绘制一个跟踪线的所有位置取决于全球定位系统时,四处移动保持点阵列的位置不太大,以保持性能?

332nm8kg  于 2023-11-21  发布在  Android
关注(0)|答案(1)|浏览(138)

我想画一条轨迹线时,移动与我的手机设备类似,它如何在三星健康应用程序时,步行/跑步/徒步旅行。
在我的应用程序中,我将每个新的位置存储到数组中,并根据这个位置数组绘制一条跟踪线。问题是位置数组的大小很快就会变得非常大。
我想知道例如在三星健康或其他应用程序中,他们正在处理这个问题?一方面,我想保持绘制的轨迹线,直到用户停止/完成当前会话,另一方面,我不想让位置数组太大,所以它会使性能成为问题。
在活动的顶部:

private var points: ArrayList<LatLng>? = null
private var line: Polyline? = null

字符串
内部onCreate

override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        points = ArrayList()
}


onMapReady

override fun onMapReady(googleMap: GoogleMap) {
        mMap = googleMap

        mMap.uiSettings.isMyLocationButtonEnabled = false

        try {
            mMap.isMyLocationEnabled = false
            mMap.uiSettings.isZoomControlsEnabled = true

            line = mMap.addPolyline(PolylineOptions())

        } catch (e: SecurityException) {
            e.printStackTrace()
        }
    }


initializeMapWithLocation方法,每次新位置添加到points数组时,我都会添加位置。

private fun initializeMapWithLocation(userLocation: LatLng) {

        mMap.uiSettings.isMyLocationButtonEnabled = false

        try {
            mMap.isMyLocationEnabled = false
            mMap.uiSettings.isZoomControlsEnabled = true

            val selectedMarkerType = MarkerType.CUSTOM_2

            val markerIcon = if (selectedMarkerType == MarkerType.DEFAULT) {
                BitmapDescriptorFactory.defaultMarker()
            } else {
                val originalBitmap = BitmapFactory.decodeResource(resources, selectedMarkerType.resourceId)
                val width = (originalBitmap.width * selectedMarkerType.scale).toInt()
                val height = (originalBitmap.height * selectedMarkerType.scale).toInt()
                val scaledMarker = Bitmap.createScaledBitmap(originalBitmap, width, height, false)
                BitmapDescriptorFactory.fromBitmap(scaledMarker)
            }

            if (marker == null) {
                // Create a new marker if it doesn't exist yet
                marker = mMap.addMarker(
                    MarkerOptions()
                        .position(userLocation)
                        .icon(markerIcon)
                        .title("Marker Title")
                )

                // Inflate the custom info window layout
                val infoWindowView = layoutInflater.inflate(R.layout.custom_info_window, null)

                // Set the custom info window as the tag of the marker
                marker?.tag = infoWindowView

                // Set the custom InfoWindow adapter for the marker
                mMap.setInfoWindowAdapter(CustomInfoWindowAdapter())
            } else {
                // Set the new position of the existing marker
                updateMarkerPosition(userLocation)

                if (points != null) {
                    points!!.add(userLocation)
                    line?.points = points as ArrayList<LatLng>
                } else {
                    // Initialize the points list if it's null
                    points = ArrayList()
                    points!!.add(userLocation)
                }

                // Get the custom info window layout from the marker's tag
                val infoWindowView = marker?.tag as View

                // Find the TextViews in the custom layout
                val latitudeTextView = infoWindowView.findViewById<TextView>(R.id.latitudeTextView)
                val longitudeTextView = infoWindowView.findViewById<TextView>(R.id.longitudeTextView)

                // Set the latitude and longitude values in the InfoWindow
                latitudeTextView.text = "Latitude: ${userLocation.latitude}"
                longitudeTextView.text = "Longitude: ${userLocation.longitude}"

                // Show the info window
                marker?.showInfoWindow()
            }

            if (!initialZoomCompleted) {
                val initialZoom = 5.0F
                val targetZoom = 16.0F
                val zoomSpeed = 500
                animateZoomIn(userLocation, initialZoom, targetZoom, zoomSpeed, false)
                initialZoomCompleted = true
            }
        } catch (e: SecurityException) {
            e.printStackTrace()
        }
    }


我在顶部的onCreate之前使用并调用了initializeMapWithLocation方法

private val locationCallback = object : LocationCallback() {
        override fun onLocationResult(locationResult: LocationResult) {
            locationResult.lastLocation?.let { location ->
                // Handle the new location here
                val newLocation = LatLng(location.latitude, location.longitude)
                initializeMapWithLocation(newLocation)
                loadingProgressBar.visibility = View.GONE
                loadingMapTextView.visibility = View.GONE
            }
        }
    }

xpcnnkqh

xpcnnkqh1#

有很多不同的方法可以做到这一点。基本的想法是你想过滤点-你想只保留一个子集的点。几个基本的方法是:
基于时间-每X秒/分钟只保留1个点。这将减少重复的点。你通常不会真的关心一秒一秒的位置细分(GPS噪音足够大,无论如何都没用)。
基于位置-只保留距离前一个点Y米或更远的点。这几乎是一个要求,因为GPS是嘈杂的,几乎不会报告相同的位置两次,即使站着不动。
删除冗余数据--如果你在时间1有一个点A,在时间2有一个点B,在时间3有一个点C,并且A、B和C都在一条线上(同样,因为如果它们靠近一条线,数据就会有噪声)--删除B。知道A和C是多余的。
丢弃明显的错误-你偶尔会得到一个刚刚关闭的GPS阅读。这在城市中心和山区是非常明显的,那里的信号反弹将显示随机读数块关闭。这些应该被检测和丢弃。一个简单的方法来检测它是,如果它没有意义的位置明智的与前一点和下一点-它将需要突然改变方向和速度。
你可以得到比这更好的,但这些都是一些简单的编码技术(特别是前两个)。

相关问题