`private val markers = mutableListOf<Marker>()`
`private val _furthestPair = MutableLiveData<Pair<Marker, Marker>?>()`
`fun findFurthestMarkers(markers: List<Marker>) { }`
`private fun connectMarkersSequentiallyFromFurthest(naverMap: NaverMap, markers: MutableList<Marker>, furthestPair: Pair<Marker, Marker>) {`
findFurthestMarkers에서 markers 안의 마커들을 2개씩 비교해 가장 거리가 먼 마커 쌍 하나인 furthestPair를 반환한다.
connectMarkersSequentiallyFromFurthest에서 furthestPair 중 첫 번째 마커를 출발점으로 잡고 currentMarker와 marker 리스트 안의 마커를 비교하면서 가장 가까운 마커와 연결시킨다.
한 번 연결된 마커는 connectedMarkers 리스트에 추가하고 markers 리스트에서는 제거해 다시 연결되지 않도록 한다.
markers 리스트에 마커가 남아 있는 동안 계속 반복한다.
private fun findFurthestMarkers(markers: List<Marker>): Pair<Marker, Marker>? {
if (markers.size < 2) return null
var furthestPair: Pair<Marker, Marker>? = null
var longestDistance = 0.0
markers.forEach { marker1 ->
markers.forEach { marker2 ->
val distance = marker1.position.distanceTo(marker2.position)
if (distance > longestDistance) {
longestDistance = distance
furthestPair = Pair(marker1, marker2)
}
}
}
return furthestPair
}
private fun connectMarkersSequentiallyFromFurthest(naverMap: NaverMap, markers: MutableList<Marker>, furthestPair: Pair<Marker, Marker>) {
var currentMarker = furthestPair.first // 시작점으로 설정할 마커
val connectedMarkers = mutableListOf(currentMarker)
markers.remove(currentMarker)
Log.d("polyline1", markers.toString())
while (markers.isNotEmpty()) {
val closestMarker = markers.minByOrNull { marker -> currentMarker.position.distanceTo(marker.position) }
closestMarker?.let { marker ->
Log.d("polyline2", marker.position.toString())
PolylineOverlay().apply {
coords = listOf(currentMarker.position, marker.position)
color = 0xFF0085FF.toInt()
map = naverMap
}
currentMarker = marker
connectedMarkers.add(marker)
markers.remove(marker)
}
}
}
private val _furthestPair = MutableLiveData<Pair<Marker, Marker>?>()
val furthestPair: LiveData<Pair<Marker, Marker>?> get() = _furthestPair
private val _furthestPair = MutableLiveData<Pair<Marker, Marker>?>()
val furthestPair: LiveData<Pair<Marker, Marker>?> = _furthestPair
백킹 프로퍼티를 사용하면 게터를 통해 추가 로직을 구현할 수 있다.
아래의 코드는 백킹 프로퍼티를 사용해 data 프로퍼티에 접근할 때마다 로그를 남기는 로직을 실행시키는 코드이다.
이 방식의 장점은 데이터를 가져올 때마다 일관되게 추가 로직을 실행할 수 있다. 데이터의 검증, 변형, 로깅 등에 유용하게 사용되며 더 깔끔하고 유지보수가 용이한 코드를 작성할 수 있다.
class ExampleViewModel : ViewModel() {
private val _data = MutableLiveData<List<String>>()
//아래와 똑같다
// val data: LiveData<List<String>> get() = _data
// 백킹 프로퍼티를 사용하여 _data의 값을 노출하지만, 커스텀 게터를 통해 추가 로직을 구현
val data: LiveData<List<String>> get() {
// 게터에 로직 추가. 여기서는 단순히 로깅을 수행하고 있음.
Log.d("ExampleViewModel", "Data accessed")
// 필요한 경우 데이터를 변형하거나, 특정 조건에 따라 다른 값을 반환할 수도 있음.
// 예: _data.value?.filter { it.isNotEmpty() } ?: emptyList()
return _data
}
}
ex) RecordDetailViewModel
class RecordDetailViewModel : ViewModel() {
}
class RecordDetailViewModel : ViewModel() {
private val _furthestPair = MutableLiveData<Pair<Marker, Marker>?>()
val furthestPair: LiveData<Pair<Marker, Marker>?> get() = _furthestPair
//아래처럼 백킹 프로퍼티를 사용할 수도 있다
/*val furthestPair: LiveData<Pair<Marker, Marker>?> get(){
Log.d("furthestPair", "RecordDetailViewModel에서 furthestPair 라이브데이터")
return _furthestPair
}*/
....
}
fun findFurthestMarkers(markers: List<Marker>) {
if (markers.size < 2) {
_furthestPair.value = null
return
}
var furthestPair: Pair<Marker, Marker>? = null
var longestDistance = 0.0
markers.forEach { marker1 ->
markers.forEach { marker2 ->
val distance = marker1.position.distanceTo(marker2.position)
if (distance > longestDistance) {
longestDistance = distance
furthestPair = Pair(marker1, marker2)
}
}
}
_furthestPair.value = furthestPair
}
private val viewModel by lazy {
ViewModelProvider(this@RecordDetailMapFragment)[RecordDetailViewModel::class.java]
}
viewModel 안에 있는 findFurthestMarkers 함수는 마커들 중 가장 멀리 있는 마커를 구하는 함수고 viewModel 안에 있는 furthestPair는 가장 멀리 있는 마커이다.
private fun observeFurthestPairAndConnectMarkers() {
viewModel.findFurthestMarkers(markers) // LiveData를 업데이트하도록 요청
viewModel.furthestPair.observe(viewLifecycleOwner, Observer { furthestPair ->
furthestPair?.let {
connectMarkersSequentiallyFromFurthest(naverMap, markers, it)
}
})
}
class RecordDetailMapFragment : Fragment(), OnMapReadyCallback {
private var _binding: FragmentRecordDetailMapBinding? = null
private val binding get() = _binding!!
private lateinit var naverMap: NaverMap
private lateinit var mapView: MapView
// 마커 리스트 생성
private val markers = mutableListOf<Marker>()
private val viewModel by lazy {
ViewModelProvider(this@RecordDetailMapFragment)[RecordDetailViewModel::class.java]
}
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?,
): View? {
_binding = FragmentRecordDetailMapBinding.inflate(inflater, container, false)
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
// mapView 변수 초기화
mapView = binding.mvRecordDetailFullMap
mapView.onCreate(savedInstanceState)
mapView.getMapAsync(this)
}
override fun onMapReady(naverMap: NaverMap) {
this.naverMap = naverMap
// 임의의 위치 데이터 목록
private val locations = listOf(
LatLng(37.4979, 127.0276),
LatLng(37.5124, 127.0589),
LatLng(37.5145, 127.0573),
LatLng(37.5273, 127.0390),
LatLng(37.5195, 127.0378),
LatLng(37.5089, 127.0468),
)
locations.forEach { latLng ->
Log.d("latLng", latLng.toString())
val marker = Marker().apply {
position = latLng
icon = OverlayImage.fromBitmap(resizeMapIcons(R.drawable.ic_marker, 100, 100))
map = naverMap
}
markers.add(marker) // 마커 리스트에 추가
}
// markers에 마커를 다 추가 후 지도에서 가장 멀리 있는 마커 구하는 함수에 인자로 markers 넣어서 호출
observeFurthestPairAndConnectMarkers()
// 카메라 위치와 줌 레벨 조정 (선택 사항)
val cameraUpdate = CameraUpdate.scrollTo(locations.first()).animate(CameraAnimation.Easing)
naverMap.moveCamera(cameraUpdate)
naverMap.moveCamera(CameraUpdate.zoomTo(10.0))
}
private fun observeFurthestPairAndConnectMarkers() {
viewModel.findFurthestMarkers(markers) // LiveData를 업데이트하도록 요청
viewModel.furthestPair.observe(viewLifecycleOwner, Observer { furthestPair ->
furthestPair?.let {
connectMarkersSequentiallyFromFurthest(naverMap, markers, it)
}
})
}
private fun resizeMapIcons(iconId: Int, width: Int, height: Int): Bitmap {
val imageBitmap = BitmapFactory.decodeResource(resources, iconId)
return Bitmap.createScaledBitmap(imageBitmap, width, height, false)
}
// 마커끼리 폴리라인 연결하는 함수
private fun connectMarkersSequentiallyFromFurthest(naverMap: NaverMap, markers: MutableList<Marker>, furthestPair: Pair<Marker, Marker>) {
var currentMarker = furthestPair.first // 시작점으로 설정할 마커
val connectedMarkers = mutableListOf(currentMarker)
markers.remove(currentMarker)
while (markers.isNotEmpty()) {
val closestMarker = markers.minByOrNull { marker -> currentMarker.position.distanceTo(marker.position) }
closestMarker?.let { marker ->
PolylineOverlay().apply {
coords = listOf(currentMarker.position, marker.position)
color = 0xFF0085FF.toInt()
map = naverMap
}
currentMarker = marker
connectedMarkers.add(marker)
markers.remove(marker)
}
}
}
override fun onStart() {
super.onStart()
mapView.onStart()
}
override fun onResume() {
super.onResume()
mapView.onResume()
}
override fun onPause() {
mapView.onPause()
super.onPause()
}
override fun onStop() {
mapView.onStop()
super.onStop()
}
override fun onLowMemory() {
super.onLowMemory()
mapView.onLowMemory()
}
override fun onSaveInstanceState(outState: Bundle) {
super.onSaveInstanceState(outState)
mapView.onSaveInstanceState(outState)
}
override fun onDestroyView() {
super.onDestroyView()
mapView.onDestroy()
_binding = null
}
}
class RecordDetailViewModel : ViewModel() {
private val _furthestPair = MutableLiveData<Pair<Marker, Marker>?>()
val furthestPair: LiveData<Pair<Marker, Marker>?> get(){
Log.d("furthestPair", "RecordDetailViewModel에서 furthestPair 라이브데이터")
return _furthestPair
}
// 지도에서 가장 멀리 있는 마커 구하는 함수
fun findFurthestMarkers(markers: List<Marker>) {
if (markers.size < 2) {
_furthestPair.value = null
return
}
var furthestPair: Pair<Marker, Marker>? = null
var longestDistance = 0.0
markers.forEach { marker1 ->
markers.forEach { marker2 ->
val distance = marker1.position.distanceTo(marker2.position)
if (distance > longestDistance) {
longestDistance = distance
furthestPair = Pair(marker1, marker2)
}
}
}
_furthestPair.value = furthestPair
}
}
markers 리스트에 marker를 다 추가하고 observeFurthestPairAndConnectMarkers를 호출해야 폴리라인이 그려진다.
뭔가, 살짝, 조금 다른 것 같지만 지금은 그냥 넘어가자