카카오맵v2] Surface redraw 질문 / 라벨 Competition.None 관련 질문

minSdk = 23
targetSdk = 34
kakao-map = { group = “com.kakao.maps.open”, name=“android”, version=“2.6.3”}

사용하고 있습니다.

카카오맵을 Activity > Fragment에서 사용중입니다.

맵 위에 있는 ViewPager나 RecyclerView의 뷰가 재사용될때 마다
[surfaceRedrawNeeded] 가 나오고
Engine pause resume 되고 맵 Surface가 redraw됩니다.

viewPager에서는 setCurrentItem(n, true) 하면 좀 덜 발생하고 setCurrentItem(n, false)로 스크롤없이 이동시키면 더 자주발생합니다.

updateSurface: mVisible = true mSurface.isValid() = true
updateSurface: mSurfaceCreated = true surfaceChanged = false visibleChanged = false
250511562 surfaceChanged – format=4 w=840 h=2081
surfaceChanged (840,2081) 1 #5 com.kakao.vectormap.graphics.gl.KGLSurfaceView{eee80ca V.E… …ID 0,0-840,2081}
250511562 surfaceRedrawNeeded
Engine{1706574455} paused
Engine{1706574455} resumed.
250511562 Changes: creating=false format=false size=true visible=false alpha=false hint=false visible=false left=false top=false z=false attached=true lifecycleStrategy=false
250511562 Cur surface: Surface(name=null)/@0x562e0f6
update, w= 840 h= 1892 mName = null mNativeObject= 0xb40000734706d2b0 sc.mNativeObject= 0xb4000073a70a4810 format= 4 caller= android.view.SurfaceView.setBufferSize:1432 android.view.SurfaceView.performSurfaceTransaction:988 android.view.SurfaceView.updateSurface:1204 android.view.SurfaceView.setFrame:559 android.view.View.layout:25748 android.widget.FrameLayout.layoutChildren:332
pST: sr = Rect(0, 82 - 840, 1974) sw = 840 sh = 1892

scrollToPosition으로 0 → 11로 넘가면 3번이상 redraw됩니다.

kakaoMap을 보면 자연스럽게 paging이 되고있는걸 볼수있어서
어떻게 처리해야할지 조언 부탁드립니다.

라벨 CompetitionType.None으로 주었을때
LabelLayer에서는 label이 전부 잘 찍히는데 LodLabelLayer에서는 인접 label이 사라집니다.
이부분도 조언 부탁드립니다.

private fun getSelectedLabelLayer() =
mKakaoSelectedLayer ?: mKakaoMap?.labelManager?.addLodLayer(
LabelLayerOptions.from(“shopSelected”)
.setCompetitionType(CompetitionType.None)
.setOrderingType(OrderingType.Rank)
.setCompetitionUnit(CompetitionUnit.IconFirst)
.setZOrder(5002)
.setLodRadius(20f)
)

RecyclerView(horizontal)을 scrollToPosition 하면 재현됩니다.

250511562 performSurfaceTransaction RenderWorker position = [0, 82, 840, 2163] surfaceSize = 840x2081
250511562 surfaceRedrawNeeded
Engine{1706673010} paused
Engine{1706673010} resumed.
250511562 finishedDrawing
250511562 performSurfaceTransaction RenderWorker position = [0, 82, 840, 1974] surfaceSize = 840x1892

updateSurface: mSurfaceCreated = true surfaceChanged = false visibleChanged = false
250511562 surfaceChanged – format=4 w=840 h=1892
250511562 surfaceRedrawNeeded
Engine{1706673010} paused
Engine{1706673010} resumed.
250511562 updateSurfacePosition RenderWorker, frameNr = 1051, position = [0, 82, 840, 1974] surfaceSize = 840x1892

BLASTBufferQueue_Java$
update, w= 840 h= 2081…
update, w= 840 h= 1892…
update, w= 840 h= 2081…
update, w= 840 h= 1892…

surface의 사이즈가 계속 변경되는것으로 보입니다.
mapView 자체 크기를 변경하는 부분은 없고 mapPadding도 주지 않고 테스트 중입니다.

recyclerView의 position을 scrollToPosition으로 0 → 11까지 이동하면 4번정도 발생합니다.

========

2024-01-31 12:56:40.078 K3fAApi D [Label] removeLabel(id=111, layerId=shopSelected) —>
2024-01-31 12:56:40.078 K3fAApi D [Label] setVisible(id=111, layerId=shopDefault, visible=1, autoMove=0) —>
2024-01-31 12:56:40.078 K3fAApi D [Label] setVisible(id=118, layerId=shopDefault, visible=0, autoMove=0) —>
2024-01-31 12:56:40.078 K3fAApi D [Label] addLabel(layer=shopSelected, styleId=270126502, labelId=118, lsLod=0) —>
2024-01-31 12:56:40.086 K3fAApi D → newCenterPoint(lat: 37.402095, lng: 127.108637, zoomLevel: -1, height: 19676.588206, animate: 1, duration: 100, makeViaPoint: 0, chain: 0)
2024-01-31 12:56:40.244 SurfaceView I 250511562 Changes: creating=false format=false size=true visible=false alpha=false hint=false visible=false left=false top=false z=false attached=true lifecycleStrategy=false
2024-01-31 12:56:40.244 SurfaceView@eee80ca I 250511562 Cur surface: Surface(name=null)/@0x9541682
2024-01-31 12:56:40.245 BLASTBufferQueue_Java I update, w= 840 h= 2081 mName = null mNativeObject= 0xb400007347077850 sc.mNativeObject= 0xb4000073a708b9d0 format= 4 caller= android.view.SurfaceView.setBufferSize:1432 android.view.SurfaceView.performSurfaceTransaction:988 android.view.SurfaceView.updateSurface:1204 android.view.SurfaceView.setFrame:559 android.view.View.layout:25748 android.widget.FrameLayout.layoutChildren:332
2024-01-31 12:56:40.245 SurfaceView@eee80ca I pST: sr = Rect(0, 82 - 840, 2163) sw = 840 sh = 2081
2024-01-31 12:56:40.246 SurfaceView@eee80ca D 250511562 performSurfaceTransaction RenderWorker position = [0, 82, 840, 2163] surfaceSize = 840x2081
2024-01-31 12:56:40.246 SurfaceView@eee80ca I updateSurface: mVisible = true mSurface.isValid() = true
2024-01-31 12:56:40.246 SurfaceView@eee80ca I updateSurface: mSurfaceCreated = true surfaceChanged = false visibleChanged = false
2024-01-31 12:56:40.246 SurfaceView I 250511562 surfaceChanged – format=4 w=840 h=2081
2024-01-31 12:56:40.246 SurfaceView@eee80ca I surfaceChanged (840,2081) 1 #5 com.kakao.vectormap.graphics.gl.KGLSurfaceView{eee80ca V.E… …ID 0,0-840,2081}
2024-01-31 12:56:40.247 SurfaceView I 250511562 surfaceRedrawNeeded
2024-01-31 12:56:40.247 K3fCore I Engine{1706673010} paused
2024-01-31 12:56:40.247 K3fCore I Engine{1706673010} resumed.
2024-01-31 12:56:40.257 SurfaceView I 250511562 Changes: creating=false format=false size=true visible=false alpha=false hint=false visible=false left=false top=false z=false attached=true lifecycleStrategy=false
2024-01-31 12:56:40.257 SurfaceView@eee80ca I 250511562 Cur surface: Surface(name=null)/@0x9541682
2024-01-31 12:56:40.258 BLASTBufferQueue_Java I update, w= 840 h= 1892 mName = null mNativeObject= 0xb400007347077850 sc.mNativeObject= 0xb4000073a708b9d0 format= 4 caller= android.view.SurfaceView.setBufferSize:1432 android.view.SurfaceView.performSurfaceTransaction:988 android.view.SurfaceView.updateSurface:1204 android.view.SurfaceView.setFrame:559 android.view.View.layout:25748 android.widget.FrameLayout.layoutChildren:332
2024-01-31 12:56:40.258 SurfaceView@eee80ca I pST: sr = Rect(0, 82 - 840, 1974) sw = 840 sh = 1892
2024-01-31 12:56:40.259 SurfaceView I 250511562 finishedDrawing
2024-01-31 12:56:40.259 SurfaceView@eee80ca D 250511562 performSurfaceTransaction RenderWorker position = [0, 82, 840, 1974] surfaceSize = 840x1892
2024-01-31 12:56:40.260 SurfaceView@eee80ca I updateSurface: mVisible = true mSurface.isValid() = true
2024-01-31 12:56:40.260 SurfaceView@eee80ca I updateSurface: mSurfaceCreated = true surfaceChanged = false visibleChanged = false
2024-01-31 12:56:40.260 SurfaceView I 250511562 surfaceChanged – format=4 w=840 h=1892
2024-01-31 12:56:40.260 SurfaceView@eee80ca I surfaceChanged (840,1892) 1 #5 com.kakao.vectormap.graphics.gl.KGLSurfaceView{eee80ca V.E… …ID 0,0-840,1892}
2024-01-31 12:56:40.260 SurfaceView I 250511562 surfaceRedrawNeeded
2024-01-31 12:56:40.261 K3fCore I Engine{1706673010} paused
2024-01-31 12:56:40.261 K3fCore I Engine{1706673010} resumed.
2024-01-31 12:56:40.263 ViewRootIm…nActivity] I registerCallbackForPendingTransactions
2024-01-31 12:56:40.269 SurfaceView D 250511562 updateSurfacePosition RenderWorker, frameNr = 1162, position = [0, 82, 840, 1974] surfaceSize = 840x1892
2024-01-31 12:56:40.270 SurfaceView@eee80ca I uSP: rtp = Rect(0, 82 - 840, 1974) rtsw = 840 rtsh = 1892
2024-01-31 12:56:40.270 SurfaceView@eee80ca I onSSPAndSRT: pl = 0 pt = 82 sx = 1.0 sy = 1.0
2024-01-31 12:56:40.270 SurfaceView@eee80ca I aOrMT: ViewRootImpl@7ed726b[MainActivity] t = android.view.SurfaceControl$Transaction@c92ddc4 fN = 1162 android.view.SurfaceView.-$$Nest$mapplyOrMergeTransaction:0 android.view.SurfaceView$SurfaceViewPositionUpdateListener.positionChanged:1660 android.graphics.RenderNode$CompositePositionUpdateListener.positionChanged:369
2024-01-31 12:56:40.270 ViewRootIm…nActivity] I mWNT: t=0xb4000073670a3d30 mBlastBufferQueue=0xb400007347074970 fn= 1162 caller= android.view.SurfaceView.applyOrMergeTransaction:1592 android.view.SurfaceView.-$$Nest$mapplyOrMergeTransaction:0 android.view.SurfaceView$SurfaceViewPositionUpdateListener.positionChanged:1660
2024-01-31 12:56:40.271 ViewRootIm…nActivity] I mWNT: t=0xb4000073670d6b30 mBlastBufferQueue=0xb400007347074970 fn= 1162 caller= android.view.ViewRootImpl$6.onFrameDraw:5582 android.view.ViewRootImpl$2.onFrameDraw:2131 android.view.ThreadedRenderer$1.onFrameDraw:788
2024-01-31 12:56:40.277 SurfaceView I 250511562 finishedDrawing
2024-01-31 12:56:40.277 SurfaceView I 250511562 Changes: creating=false format=false size=true visible=false alpha=false hint=false visible=false left=false top=false z=false attached=true lifecycleStrategy=false
2024-01-31 12:56:40.278 SurfaceView@eee80ca I 250511562 Cur surface: Surface(name=null)/@0x9541682
2024-01-31 12:56:40.278 BLASTBufferQueue_Java I update, w= 840 h= 2081 mName = null mNativeObject= 0xb400007347077850 sc.mNativeObject= 0xb4000073a708b9d0 format= 4 caller= android.view.SurfaceView.setBufferSize:1432 android.view.SurfaceView.performSurfaceTransaction:988 android.view.SurfaceView.updateSurface:1204 android.view.SurfaceView.setFrame:559 android.view.View.layout:25748 android.widget.FrameLayout.layoutChildren:332
2024-01-31 12:56:40.278 SurfaceView@eee80ca I pST: sr = Rect(0, 82 - 840, 2163) sw = 840 sh = 2081
2024-01-31 12:56:40.279 SurfaceView@eee80ca D 250511562 performSurfaceTransaction RenderWorker position = [0, 82, 840, 2163] surfaceSize = 840x2081
2024-01-31 12:56:40.279 SurfaceView@eee80ca I updateSurface: mVisible = true mSurface.isValid() = true
2024-01-31 12:56:40.279 SurfaceView@eee80ca I updateSurface: mSurfaceCreated = true surfaceChanged = false visibleChanged = false
2024-01-31 12:56:40.279 SurfaceView I 250511562 surfaceChanged – format=4 w=840 h=2081
2024-01-31 12:56:40.279 SurfaceView@eee80ca I surfaceChanged (840,2081) 1 #5 com.kakao.vectormap.graphics.gl.KGLSurfaceView{eee80ca V.E… …ID 0,0-840,2081}
2024-01-31 12:56:40.281 SurfaceView I 250511562 surfaceRedrawNeeded
2024-01-31 12:56:40.283 K3fCore I Engine{1706673010} paused
2024-01-31 12:56:40.283 K3fCore I Engine{1706673010} resumed.
2024-01-31 12:56:40.293 SurfaceView I 250511562 finishedDrawing
2024-01-31 12:56:40.295 SurfaceView I 250511562 Changes: creating=false format=false size=true visible=false alpha=false hint=false visible=false left=false top=false z=false attached=true lifecycleStrategy=false
2024-01-31 12:56:40.296 SurfaceView@eee80ca I 250511562 Cur surface: Surface(name=null)/@0x9541682
2024-01-31 12:56:40.296 BLASTBufferQueue_Java I update, w= 840 h= 1892 mName = null mNativeObject= 0xb400007347077850 sc.mNativeObject= 0xb4000073a708b9d0 format= 4 caller= android.view.SurfaceView.setBufferSize:1432 android.view.SurfaceView.performSurfaceTransaction:988 android.view.SurfaceView.updateSurface:1204 android.view.SurfaceView.setFrame:559 android.view.View.layout:25748 android.widget.FrameLayout.layoutChildren:332
2024-01-31 12:56:40.296 SurfaceView@eee80ca I pST: sr = Rect(0, 82 - 840, 1974) sw = 840 sh = 1892
2024-01-31 12:56:40.297 SurfaceView@eee80ca D 250511562 performSurfaceTransaction RenderWorker position = [0, 82, 840, 1974] surfaceSize = 840x1892
2024-01-31 12:56:40.297 SurfaceView@eee80ca I updateSurface: mVisible = true mSurface.isValid() = true
2024-01-31 12:56:40.297 SurfaceView@eee80ca I updateSurface: mSurfaceCreated = true surfaceChanged = false visibleChanged = false
2024-01-31 12:56:40.297 SurfaceView I 250511562 surfaceChanged – format=4 w=840 h=1892
2024-01-31 12:56:40.297 SurfaceView@eee80ca I surfaceChanged (840,1892) 1 #5 com.kakao.vectormap.graphics.gl.KGLSurfaceView{eee80ca V.E… …ID 0,0-840,1892}
2024-01-31 12:56:40.297 SurfaceView I 250511562 surfaceRedrawNeeded
2024-01-31 12:56:40.297 K3fCore I Engine{1706673010} paused
2024-01-31 12:56:40.297 K3fCore I Engine{1706673010} resumed.
2024-01-31 12:56:40.299 ViewRootIm…nActivity] I registerCallbackForPendingTransactions
2024-01-31 12:56:40.303 SurfaceView D 250511562 updateSurfacePosition RenderWorker, frameNr = 1163, position = [0, 82, 840, 1974] surfaceSize = 840x1892
2024-01-31 12:56:40.303 SurfaceView@eee80ca I uSP: rtp = Rect(0, 82 - 840, 1974) rtsw = 840 rtsh = 1892
2024-01-31 12:56:40.303 SurfaceView@eee80ca I onSSPAndSRT: pl = 0 pt = 82 sx = 1.0 sy = 1.0
2024-01-31 12:56:40.303 SurfaceView@eee80ca I aOrMT: ViewRootImpl@7ed726b[MainActivity] t = android.view.SurfaceControl$Transaction@e6ae373 fN = 1163 android.view.SurfaceView.-$$Nest$mapplyOrMergeTransaction:0 android.view.SurfaceView$SurfaceViewPositionUpdateListener.positionChanged:1660 android.graphics.RenderNode$CompositePositionUpdateListener.positionChanged:369
2024-01-31 12:56:40.303 ViewRootIm…nActivity] I mWNT: t=0xb400007367119210 mBlastBufferQueue=0xb400007347074970 fn= 1163 caller= android.view.SurfaceView.applyOrMergeTransaction:1592 android.view.SurfaceView.-$$Nest$mapplyOrMergeTransaction:0 android.view.SurfaceView$SurfaceViewPositionUpdateListener.positionChanged:1660
2024-01-31 12:56:40.304 ViewRootIm…nActivity] I mWNT: t=0xb4000073670e3d90 mBlastBufferQueue=0xb400007347074970 fn= 1163 caller= android.view.ViewRootImpl$6.onFrameDraw:5582 android.view.ViewRootImpl$2.onFrameDraw:2131 android.view.ThreadedRenderer$1.onFrameDraw:788
2024-01-31 12:56:40.307 SurfaceView I 250511562 finishedDrawing

  1. MapView 와 RecyclerView 가 어떻게 배치됐는지 확인할 수 있도록 레이아웃 xml 코드를 공유 부탁드립니다.

  2. 먼저, 레이어가 제대로 추가 되었는지 확인을 위해 위와 같이 LodLabelLayer 추가 후 그 다음에 아래 코드를 실행시켜서, CompetitionType 이 어떤 값으로 찍히는지 확인 부탁 드립니다.

    kakaoMap.getLabelManager().getLodLayer(“shopSelected”).getCompetitionType();

    • LabelLayer 에 사용됐던 LayerId 를 LodLabelLayer 에 똑같이 사용하면 LodLabelLayer 추가가 무시됩니다.

MainActivity 하단에 바텀탭바가 있고 > ViewPager > MapFragment 형태로 만들어져있습니다.

 <androidx.constraintlayout.widget.ConstraintLayout
        android:id="@+id/clRoot"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@color/white"
        tools:context=".presentation.ui.main.MainActivity"
        >

        <FrameLayout
            android:id="@+id/flMap"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            app:layout_constraintTop_toTopOf="parent"
            app:layout_constraintBottom_toBottomOf="parent"
            tools:background="@color/color_special_3"
            />

 <!--  선택된 매장 정보  -->
        <androidx.appcompat.widget.LinearLayoutCompat
            android:id="@+id/clShopInfo"
            android:orientation="vertical"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="@color/color_white_1"
            app:layout_constraintBottom_toBottomOf="parent"
            >

            <androidx.viewpager2.widget.ViewPager2 (or RecyclerView)
                android:id="@+id/shopViewPager"
                android:orientation="horizontal"
                android:layout_width="match_parent"
                android:layout_height="160dp"
                app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
                tools:listitem="@layout/view_shop_info"
                />

        </androidx.appcompat.widget.LinearLayoutCompat>
</androidx.constraintlayout.widget.ConstraintLayout>

Fragment의 onViewCreated()

    private fun initMapView() {
        // 카카오 맵뷰 생성
        mKakaoMapView = mKakaoMapView ?: MapView(activity)
        dataBinding.flMap.addView(mKakaoMapView,
            LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT)
        )
        startMapView()
    }


private fun startMapView() {
        // 맵 뷰 시작
        mKakaoMapView?.start(
            object : MapLifeCycleCallback() {
                override fun onMapDestroy() {
                    mKakaoMap = null
                    mKakaoMapView = null
                }
                override fun onMapError(error: Exception?) {
                    mKakaoMap = null
                }
            },
            object : KakaoMapReadyCallback() {
                override fun getZoomLevel(): Int {
                    return 15
                }
                override fun getPosition(): LatLng {
                    return LatLng.from(37.394761, 127.111217)
                }
                override fun onMapReady(kakaoMap: KakaoMap) {
                    mKakaoMap = kakaoMap
                    kakaoMap.setPoiClickable(false)
                    loadedKakaoMap()
                    // 지도 클릭
                    kakaoMap.setOnMapClickListener { _, position, screenPoint, poi ->
                       
                    }
                    // 라벨 클릭
                    kakaoMap.setOnLabelClickListener {  _, layer, label ->
                      
                    }

                    // 지도 이동 시작
                    kakaoMap.setOnCameraMoveStartListener { _, gestureType ->
                       
                    }
                    // 지도 이동 완료
                    kakaoMap.setOnCameraMoveEndListener { _, cameraPos, gestureType ->

                    }
                }
            })
    }

올려주신 레이아웃 코드로 단순하게 MapView 와 ViewPager2 를 넣고 setCurrentItem() 를 호출했을 때, 지도가 pause/resume 되거나 redraw 가 발생하지 않았습니다. 개발하시는 환경 쪽에서 MapView 의 크기가 업데이트 되거나 redraw 될만한 설정이 있지 않은지 확인 해보시면 좋을 것 같습니다.

로그로 MapView의 사이즈가 변동되는것 같아서 화면 만들어 진 후 강제로 height 고정시켜두니 redraw가 멈췄습니다.
Fragment가 ViewPager안에 있어서 그런건지 모르겠네요.

val screenHeight = it.context.getScreenHeight()
mKakaoMapView?.updateLayoutParams {
height = screenHeight - actionBarHeight
}

그렇군요. MapView 외부적인 요인으로 크기가 변경되거나 업데이트 되는 것은 View 의 라이프사이클 상 필요한 부분이라 임의로 막는 건 어렵습니다. 레이아웃 부분은 앱 쪽의 구현 부분이라 따로 코멘트 드릴 수 없지만, 의도하지 않았거나 또는 불필요하게 View 크기 및 업데이트가 되지 않도록 레이아웃 구성을 확인해보시면 좋을 것 같습니다.