Lock in $30 Savings on PRO—Offer Ends Soon! ⏳

NAVER Map in Jetpack Compose

NAVER Map in Jetpack Compose

11/19 (토) DevFest 2022 - GDG Songdo, Incheon & GDSC Inha, TUKorea 행사에서 발표한 자료입니다.
https://festa.io/events/2758

아래 오픈소스 라이브러리에 대한 내용입니다.
https://github.com/fornewid/naver-map-compose

Sungyong An

November 19, 2022
Tweet

More Decks by Sungyong An

Other Decks in Programming

Transcript

  1. Sungyong An NAVER WEBTOON Android GDE @fornewid Link: h tt

    ps://github.com/fornewid Slide Template ठۄ੉٘ ೞױী ݂௼о ੓णפ׮.
  2. Link: h tt ps://developer.android.com/develop/ui/views/layout/declaring-layout <?xml version="1.0" encoding="utf-8"?> <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent"

    android:orientation="vertical" > <TextView android:id="@+id/text" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Hello, I am a TextView" /> <Button android:id="@+id/button" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Hello, I am a Button" /> </LinearLayout> View System അসীࢲח View Systemਵ۽ ѐߊೞח Ѫ੉ ੊ࣼೡ Ѫ эणפ׮. ୊਺ উ٘۽੉٘ ѐߊਸ ੽ೡ ٸب ࠁా Layout XMLࠗఠ द੘ೞભ.
  3. Link: h tt ps://developer.android.com/jetpack/compose Jetpack Compose (Modern Android Development )

    ਃ્ীח Jetpack Composeо ݆੉ ࣗѐغҊ ੓ҳਃ. ࢜۽਍ ࣗध ੺߈਷ Composeੌ ੿ب۽ ҙबਸ ߉Ҋ ੓णפ׮.
  4. Link: h tt ps://developer.android.com/jetpack/compose/interop/migration-strategy Migrate from View to Compose 🤔

    Ӓ۞׮ࠁפ ݆਷ ٜ࠙੉ Viewܳ Compose۽ ੹ജೞҊ ੓Ѣա, ੹ജਸ Ҋ۰ೞҊ ੓ਸѢۄ ࢤп೤פ׮.
  5. Link: h tt ps://github.com/navermaps/android-map-sdk Official SDK based on View 🤔

    ֎੉ߡ૑ب SDKח View Systemਵ۽ ҳഅغয ੓णפ׮. Ӓېࢲ ੉Ѧ ஹನૉীࢲ যڌѱ ॶ ࣻ ੓ਸ૑ Ҋ޹೮ભ.
  6. How to use in Jetpack Compose? -(1) ݽٚ ௏٘ܳ Compose۽

    ׮द ੘ࢿೠ׮ -(2) ೨ब ௏٘ܳ ܻ࠙ೞৈ Composeীࢲ ੤ഝਊೠ׮ -(3) ࢚ഐ ਍ਊࢿ APIܳ ࢎਊೞৈ ӝઓ ௏٘ܳ ېೝೠ׮ ݢ੷ ݽٚ ௏٘ܳ Compose۽ ৮੹൤ ࢜۽ ҳഅೞח ߑߨ੉ ੓णפ׮. ׮਺ਵ۽ ೨ब ௏٘ܳ ܻ࠙ೞৈ, ੌࠗ࠙ ࠗ࠙݅ Compose۽ ੘ࢿೞח ߑߨ੉ ੓णפ׮. ݃૑݄ਵ۽ ࢚ഐ਍ਊࢿ APIܳ ੉ਊೞৈ, ӝઓ ௏٘ܳ ېೝೞח ߑߨب ੓णפ׮.
  7. How to use in Jetpack Compose? -(1) ݽٚ ௏٘ܳ Compose۽

    ׮द ੘ࢿೠ׮ (X) -(2) ೨ब ௏٘ܳ ܻ࠙ೞৈ Composeীࢲ ੤ഝਊೠ׮ (X) -(3) ࢚ഐ ਍ਊࢿ APIܳ ࢎਊೞৈ ӝઓ ௏٘ܳ ېೝೠ׮ ✅ NAVER Map SDK != Open Source Project ইऔѱب ֎੉ߡ૑ب SDKח য়೑ࣗझо ইפۄࢲ ࣻ੿ೡ ߑߨ੉ হणפ׮. Ӓېࢲ ݃૑݄ ߑߨੋ ӝઓ ௏٘ܳ ېೝೞח ߑधਵ۽ ૓೯೮णפ׮.
  8. Link: h tt ps://github.com/Moop-App/Moop-Android/pull/120 (1) Migrate using Compose API ୊਺ীח

    Compose APIܳ ੉ਊ೧ࢲ 
 ష੉ ೐۽ં౟ী ࢤ૞۽ ٸ۰߅ח(?) ੘সਸ ೮णפ׮.
  9. Link: h tt ps://github.com/fornewid/naver-map-compose (2) For Jetpack Compose Unofficial wrapper

    library Ӓ ׮਺ীח ખ ؊ ҕਊചػ ਬૉா੉झী ݏ୾ 
 Compose wrapper ۄ੉࠳۞ܻܳ ٜ݅঻णפ׮.
  10. Toy Project੄ UseCase ҳഅೞӝ Link: h tt ps://github.com/Moop-App/Moop-Android/pull/120 ݢ੷ ష੉

    ೐۽ં౟ী ҳഅೠ 5о૑ ਬૉா੉झܳ ࢓ಝࠁѷणפ׮.
  11. MapView class MapViewActivity : AppCompatActivity() { private var mapView: MapView?

    = null override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_map_view) mapView = findViewById(R.id.map_view) } } Activityীࢲ ࢸ੿೧઱ݶ ؾפ׮
  12. MapView class MapComposeActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?)

    { super.onCreate(savedInstanceState) setContent { ... } } } Link: h tt ps://developer.android.com/jetpack/compose/interop/interop-apis#compose-in-views Composeীࢲח Layout XML ؀न setContentী Composableਸ ੹׳ೞݶ ؾפ׮
  13. MapView val context = LocalContext.current AndroidView(factory = { context ->

    MapView(context) }) Link: h tt ps://developer.android.com/jetpack/compose/interop/interop-apis#views-in-compose ੉ۧѱ AndroidViewۄח APIо ઁҕغҊ ੓যࢲ 
 factoryীࢲ MapViewܳ ૒੽ ࢤࢿೞݶ ؾפ׮
  14. MapView Lifecycle override fun onCreate(...) { super.onCreate(...) mapView?.onCreate(...) } override

    fun onStart() { super.onStart() mapView?.onStart() } override fun onResume() { super.onResume() mapView?.onResume() } override fun onPause() { super.onPause() mapView?.onPause() } override fun onStop() { super.onStop() mapView?.onStop() } override fun onDestroy() { super.onDestroy() mapView?.onDestroy() } 🤔 View Systemীࢲח ੉۠ ഋక۽ ഐ୹ೞҊ ੓঻ਸ ѩפ׮
  15. MapView Lifecycle val context = LocalContext.current AndroidView(factory = { context

    -> MapView(context) }) ׮द ੉੹ ௏٘۽ جইоࠁѷणפ׮
  16. MapView Lifecycle val context = LocalContext.current val mapView = remember

    { MapView(context) } AndroidView(factory = { mapView }) Link: h tt ps://developer.android.com/jetpack/compose/pe rf ormance/bestpractices#use-remember MapView੄ ೣࣻܳ ഐ୹೧ঠ ೞפө, ݢ੷ remember ೣࣻܳ ੉ਊ೧ࢲ MapViewܳ ܻ࠙೧յ ѩפ׮
  17. MapView Lifecycle val context = LocalContext.current val mapView = remember(context){

    MapView(context) } // (X) AndroidView(factory = { mapView }) Link: h tt ps://developer.android.com/jetpack/compose/pe rf ormance/bestpractices#use-remember ੉ ٸ remember ೣࣻী keyܳ ֍ਵݶ, keyо ߸҃ؼ ٸ݃׮ MapViewܳ ׮द ࢤࢿೞ޲۽ ઱੄೧ঠ ೤פ׮
  18. MapView Lifecycle val context = LocalContext.current val mapView = remember

    { MapView(context) } AndroidView(factory = { mapView }) Link: h tt ps://developer.android.com/jetpack/compose/pe rf ormance/bestpractices#use-remember ৈӝࢲח MapViewо Compositionীࢲ݅ ೠߣ ࢤࢿغب۾ keyܳ ֍૑ ঋणפ׮
  19. MapView Lifecycle val mapView = rememberMapViewWithLifecycle() AndroidView(factory = { mapView

    }) @Composable fun rememberMapViewWithLifecycle(): MapView { val context = LocalContext.current val mapView = remember { MapView(context) } ... return mapView } MapViewܳ ܻ࠙೮ਵפ, ੉ઁח Lifecycleਸ ୊ܻ೧ࠅөਃ?
  20. MapView Lifecycle private fun getMapLifecycleObserver( mapView: MapView, savedInstanceState: Bundle? )

    = LifecycleEventObserver { _, event -> when (event) { Lifecycle.Event.ON_CREATE -> mapView.onCreate(savedInstanceState) Lifecycle.Event.ON_START -> mapView.onStart() Lifecycle.Event.ON_RESUME -> mapView.onResume() Lifecycle.Event.ON_PAUSE -> mapView.onPause() Lifecycle.Event.ON_STOP -> mapView.onStop() Lifecycle.Event.ON_DESTROY -> mapView.onDestroy() else -> throw IllegalStateException() } } LifecycleEventObserverܳ ੉ਊ೧ࢲ пп੄ ੉߮౟݃׮ MapView੄ ೣࣻܳ ഐ୹೧સפ׮
  21. MapView Lifecycle fun rememberMapViewWithLifecycle(): MapView { ... val lifecycle =

    LocalLifecycleOwner.current.lifecycle DisposableEffect(lifecycle, mapView) { val lifecycleObserver = getMapLifecycleObserver(mapView, null) lifecycle.addObserver(lifecycleObserver) onDispose { lifecycle.removeObserver(lifecycleObserver) } } return mapView } ӒܻҊ Observerܳ Lifecycleী োѾ/೧ઁ೧઱ח ௏٘ܳ ੘ࢿೞݶ ؾפ׮
  22. MapView Lifecycle fun rememberMapViewWithLifecycle(): MapView { ... val lifecycle =

    LocalLifecycleOwner.current.lifecycle DisposableEffect(lifecycle, mapView) { val lifecycleObserver = getMapLifecycleObserver(mapView, null) lifecycle.addObserver(lifecycleObserver) onDispose { lifecycle.removeObserver(lifecycleObserver) } } return mapView } Link: h tt ps://developer.android.com/jetpack/compose/side-e ff ects#disposablee ff ect ੉ ٸ, DisposableEffect৬ onDisposeۄח Ѫਸ ੉ਊ೧ࢲ Observer੄ োѾҗ ೧ઁ द੼ਸ ੿੄೧઱ݶ غחؘਃ
  23. Compositionਸ ઙܐೠ റ, ੿ܻ೧ঠ ೡ ٸ ࢎਊೠ׮. Source: h tt

    ps://medium.com/mobile-app-development-publication/a4867f876928 DisposableEffect
  24. ഐ୹೧ঠ ೞח Lifecycle ೣࣻо ই૒ թই੓׮. Lifecycle Link: h tt

    ps://navermaps.github.io/android-map-sdk/guide-ko/2-1.html
  25. SavedInstanceState class MapViewActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?)

    { ... mapView?.onCreate(savedInstanceState) } override fun onSaveInstanceState(outState: Bundle) { super.onSaveInstanceState(outState) mapView?.onSaveInstanceState(outState) } } View Systemীࢲח onCreate৬ onSaveInstanceStateীࢲ ೣࣻܳ ഐ୹೧઱ݶ غ঻ҳਃ
  26. SavedInstanceState val savedInstanceState = rememberSavedInstanceState() val mapView = rememberMapViewWithLifecycle(savedInstanceState) AndroidView(factory

    = { mapView }) @Composable fun rememberSavedInstanceState(): Bundle { return rememberSaveable { Bundle() } // Survives config changes } Composeীࢲח Bundleਸ ૒੽ ҙܻೞח ߑߨਸ ࢎਊೡ ࣻ ੓যਃ ੉ ٸ, Bundleਸ rememberSaveable۽ ੷੢೤פ׮
  27. SavedInstanceState @Composable fun rememberMapViewWithLifecycle(savedInstanceState: Bundle): MapView { ... DisposableEffect(lifecycle, mapView,

    savedInstanceState) { val lifecycleObserver = getMapLifecycleObserver( mapView, savedInstanceState.takeUnless { it.isEmpty } ) onDispose { ... mapView.onSaveInstanceState(savedInstanceState) } } return mapView } Ӓېࢲ ૒੽ ҙܻೞח Bundle ё୓ܳ ੹׳೧઱ݶ ৮ܐؾפ׮
  28. SavedInstanceState private fun getMapLifecycleObserver( mapView: MapView, savedInstanceState: Bundle? ) =

    LifecycleEventObserver { _, event -> when (event) { Lifecycle.Event.ON_CREATE -> mapView.onCreate(savedInstanceState) ... } } LifecycleEventObserverীࢲب োѾ೧઱ݶ غѷભ
  29. onLowMemory fun MapView.componentCallbacks(): ComponentCallbacks { return object : ComponentCallbacks {

    override fun onConfigurationChanged(config: Configuration) {} override fun onLowMemory() { [email protected]() } } } Composeীࢲח LifecycleObserver୊ۢ 
 ComponentCallbacksܳ ٜ݅যࢲ ഐ୹ೞݶ ؾפ׮
  30. onLowMemory fun rememberMapViewWithLifecycle(): MapView { ... val lifecycle = LocalLifecycleOwner.current.lifecycle

    DisposableEffect(lifecycle, mapView) { val callbacks = mapView.componentCallbacks() context.registerComponentCallbacks(callbacks) onDispose { context.unregisterComponentCallbacks(callbacks) } } return mapView } ١۾/೧ઁೞח ࠗ࠙਷ খࢶ җ੿җ زੌ೤פ׮
  31. MapViewח View ৉ೡ݅ਸ ׸׼ೠ׮. APIܳ ഐ୹ೞ۰ݶ ੋఠಕ੉झ ৉ೡਸ ೞח NaverMap

    ё୓о ೙ਃೞ׮. OnMapReadyCallback Link: h tt ps://navermaps.github.io/android-map-sdk/guide-ko/2-1.html MapView۽ ૑ب ࠁৈ઱ח ੘স਷ ՘լ૑݅ খਵ۽ ૑بܳ ஶ౟܀ೞח ੘সٜ੉ ೙ਃ೤פ׮
  32. OnMapReadyCallback private val callback = object : OnMapReadyCallback { override

    fun onMapReady(naverMap: NaverMap) { ... } } mapView?.getMapAsync(callback) NaverMap ё୓ܳ ঳ਵ۰ݶ, OnMapReadyCallbackਸ ࢎਊೞৈ Callback ഋక۽ оઉয়ݶ ؾפ׮
  33. OnMapReadyCallback suspend fun MapView.awaitMap(): NaverMap { return suspendCoroutine { continuation

    -> getMapAsync { continuation.resume(it) } } } val coroutineScope = rememberCoroutineScope() val mapView = rememberMapViewWithLifecycle(...) coroutineScope.launch { val naverMap: NaverMap = mapView.awaitMap() } Link: h tt ps://developer.android.com/jetpack/compose/side-e ff ects#remembercoroutinescope Composeীࢲח ௏ܖ౯ਵ۽ оઉয়ח ೣࣻܳ ٜ݅঻ҳਃ ೙ਃೡ ٸ CoroutineScopeܳ ࢤࢿ೧ NaverMap ё୓ܳ оઉৢ ࣻ ੓णפ׮
  34. Compositionਸ ઙܐೠ റ ੗زਵ۽ ஂࣗغب۾ ߧਤо ૑੿ػ ௏ܖ౯ਸ प೯ೠ׮. Source:

    h tt ps://medium.com/mobile-app-development-publication/a4867f876928 rememberCoroutineScope
  35. OnMapReadyCallback suspend fun MapView.awaitMap(): NaverMap { return suspendCoroutine { continuation

    -> getMapAsync { continuation.resume(it) } } } val coroutineScope = rememberCoroutineScope() val mapView = rememberMapViewWithLifecycle(...) coroutineScope.launch { val naverMap: NaverMap = mapView.awaitMap() } ✅ ੉ۧѱ NaverMap ё୓ܳ оઉয়ח ؘө૑ ޖࢎ൤ ݃ଢ଼णפ׮
  36. ૑ب ২࣌ mapView.getMapAsync { naverMap -> if (isDarkTheme) { naverMap.mapType

    = NaverMap.MapType.Navi naverMap.isNightModeEnabled = true } else { naverMap.mapType = NaverMap.MapType.Basic naverMap.isNightModeEnabled = false } } ঠрݽ٘ա ૑ب੄ ఋੑ ١ਸ ߸҃ೞҊ र׮ݶ, NaverMap ё୓ী׮о ૒੽ mapType ١ਸ ࢸ੿೧઱ݶ ؾפ׮
  37. ૑ب ২࣌ AndroidView(factory = { mapView.apply { coroutineScope.launch { val

    naverMap = awaitMap() if (isDarkTheme) { naverMap.mapType = NaverMap.MapType.Navi naverMap.isNightModeEnabled = true } else { naverMap.mapType = NaverMap.MapType.Basic naverMap.isNightModeEnabled = false } } } }) Composeীࢲب Ѣ੄ زੌೠ ௏٘ܳ Ӓ؀۽ ࢎਊೞݶ غѷणפ׮
  38. ૑ب ࣘࢿ val context = LocalContext.current val mapView = remember

    { MapView(context, naverMapOptions()) } AndroidView(factory = { mapView }) private fun naverMapOptions() = NaverMapOptions() .extent(LatLngBounds.from(LatLng(31.43, 122.37),LatLng(44.35, 132.0))) .locationButtonEnabled(true) .scaleBarEnabled(false) .minZoom(6.0) .camera(CameraPosition(LatLng.INVALID, 12.0)) ੉۠ ٜࠗ࠙ب ௏٘۽ ੿੄ೞҊ, MapView ࢤࢿ੗ী ੹׳ೞݶ ؾפ׮ ل ׮ ࠺तೠ ௏٘о ٜ݅য઎ભ?
  39. ૑ب ੉߮౟ mapView.getMapAsync { naverMap -> naverMap.setOnMapClickListener { _, _

    -> /* Do domething*/ } } NaverMapী Click Listenerܳ ١۾ೞח ௏٘ੑפ׮
  40. ૑ب ੉߮౟ AndroidView(factory = { mapView.apply { coroutineScope.launch { val

    naverMap = awaitMap() naverMap.setOnMapClickListener { _, _ -> /* Do domething*/ } } } }) Composeীࢲب زੌೠ ௏٘ܳ ੘ࢿೞݶ ؾפ׮
  41. ݃ழ val marker = Marker().apply { captionText = "caption" position

    = LatLng(..., ...) icon = OverlayImage.fromResource(R.drawable.marker_icon) setOnClickListener { ... true } } Viewٚ Composeٚ ࢚ҙহ੉ ݃ழܳ ੉ۧѱ ࢤࢿ೤פ׮
  42. Example: ӓ੢ ݃ழ ҙܻೞӝ var markers = listOf<Marker>() fun render(theaters:

    List<TheaterMarkerUiModel>) { markers.forEach { it.map = null } markers = theaters.map { theater -> Marker().apply { ... map = naverMap } } } ӓ੢ ݾ۾ਸ ݃ழ۽ ಴दೞח ৘ઁ ௏٘ੑפ׮ Markerী NaverMapਸ ࢸ੿ೞҊ, null۽ ೧ઁ೧ঠ ೤פ׮
  43. Example: ӓ੢ ݃ழ ҙܻೞӝ var markers by remember { mutableStateOf<List<Marker>>(emptyList())

    } LaunchedEffect(theaters) { val naverMap = mapView.awaitMap() markers.forEach { it.map = null } markers = theaters.map { theater -> Marker().apply { ... map = naverMap } } } Link: h tt ps://developer.android.com/jetpack/compose/side-e ff ects#launchede ff ect Composeীࢲب زੌೠ ௏٘ܳ ੘ࢿ೮ҳਃ LaunchedEffectܳ ࢎਊ೧ࢲ theaters੉ ߄Չ ٸ݅ ݃ழܳ ׮द Ӓܻب۾ ೮णפ׮
  44. Composable ߧਤীࢲ suspend funܳ ഐ୹ೡ ٸ ࢎਊೠ׮. Composition द੼ ژח

    keyо ߸҃ؼ ٸ݃׮ ׮द ഐ୹ػ׮. LaunchedEffect Source: h tt ps://medium.com/mobile-app-development-publication/a4867f876928
  45. ஠ݫۄ ੉ز // move naverMap.moveCamera(CameraUpdate.zoomTo(12.0)) // animation naverMap.moveCamera( CameraUpdate .scrollAndZoomTo(LatLng(...,

    ...), 16.0) .animate(CameraAnimation.Fly) ) Link: h tt ps://navermaps.github.io/android-map-sdk/guide-ko/3-2.html ஠ݫۄܳ ੉زೞח ௏٘۽, গפݫ੉࣌ ৈࠗী ٮۄ ࢎਊߑߨ੉ ઑӘ ׮ܵפ׮ ׮নೠ APIо ੓ਵפ, ֎੉ߡ૑ب SDK੄ ޙࢲܳ ଵҊೞݶ ب਑ؼ Ѫ эणפ׮
  46. Example: ݃ழ ࢶఖೞӝ Marker().apply { setOnClickListener { /* Marker Selected

    */ naverMap.moveCamera(...) } } mapView.getMapAsync { naverMap -> naverMap.setOnMapClickListener { _, _ -> /* Marker Unselected */ naverMap.moveCamera(...) } } ݃ழ৬ ૑بܳ ௿ܼೞݶ ஠ݫۄܳ ੉زೞח ৘ઁ ௏٘ੑפ׮
  47. Example: ݃ழ ࢶఖೞӝ var selectedTheater by remember { mutableStateOf<TheaterMarkerUiModel?>)(null) }

    Marker().apply { setOnClickListener { /* Marker Selected */ selectedTheater = theater } } mapView.getMapAsync { naverMap -> naverMap.setOnMapClickListener { _, _ -> /* Marker Unselected */ selectedTheater = null } } Composeীࢲب زੌೞѱ ೡ ࣻ ੓૑݅, ࢶఖػ ӓ੢ਸ ࢚క۽ ੿੄೧فҊ ࢚కо ߸҃ؼ ٸ ஠ݫۄܳ ੉زೞח ߑߨਸ ࢎਊ೮णפ׮
  48. Composeীࢲ ҙ଴ೡ ࣻ ੓ח MutableState<T>ܳ ࢤࢿೞח ೣࣻ. valueо ߸҃غݶ, valueܳ

    ੍ח Composable ೣࣻ੄ Recomposition੉ ৘ডػ׮. mutableStateOf Link: h tt ps://developer.android.com/jetpack/compose/state#state-in-composables interface MutableState<T> : State<T> { override var value: T } var value by remember { mutableStateOf(default) } Recompositionীࢲ ੉੹ valueܳ ਬ૑ೞ۰ݶ rememberܳ ࢎਊ೧ঠ ೠ׮.
  49. Example: ݃ழ ࢶఖೞӝ var selectedTheater by remember { mutableStateOf<TheaterMarkerUiModel?>)(null) }

    LaunchedEffect(selectedTheater) { val naverMap = mapView.awaitMap() if (selectedTheater != null) { naverMap.moveCamera(...) } else { naverMap.moveCamera(...) } } LaunchedEffectܳ ੉ਊೞৈ, ࢶఖػ ӓ੢ ч੉ ߸҃ؼ ٸ݃׮ ੸׼ೠ ਤ஖۽ ஠ݫۄܳ ੉زೡ ࣻ ੓ѷणפ׮
  50. ৈӝࢲ ਫ਼Ӭ! Architecture: Unidirectional Data Flow var name by remember

    { mutableStateOf("") } OutlinedTextField( value = name, onValueChange = { name = it }, label = { Text("Name") } ) Link: h tt ps://developer.android.com/jetpack/compose/architecture 
 ࢚కח ইې۽ ੉زೞҊ ੉߮౟ח ਤ۽ ੉زೞח ٣੗ੋ ಁఢ.
  51. val savedInstanceState = rememberSavedInstanceState() val mapView = rememberMapViewWithLifecycle(savedInstanceState, naverMapOptions()) AndroidView(factory

    = { mapView.apply { coroutineScope.launch { val naverMap = awaitMap() naverMap.mapType = NaverMap.MapType.Navi naverMap.isNightModeEnabled = true naverMap.setOnMapClickListener { _, _ -> /* Do domething*/ } } } }) খীࢲ ੘ࢿ೮؍ ௏٘о ࢶ঱ഋ UIী ੸೤ೞѱ ҳഅغ঻ח૑ ࢤп೧ࠇद׮
  52. @Composable fun NaverMap( modifier: Modifier = Modifier, mapOptions: NaverMapOptions =

    ..., mapProperties: MapProperties = ..., onMapClick: (PointF, LatLng) -> Unit = { _, _ -> }, ) { val savedInstanceState = rememberSavedInstanceState() val mapView = rememberMapViewWithLifecycle(savedInstanceState, mapOptions) AndroidView(factory = { mapView.apply { coroutineScope.launch { val naverMap = awaitMap() naverMap.mapType = mapProperties.mapType naverMap.isNightModeEnabled = mapProperties.isNightModeEnabled naverMap.setOnMapClickListener(onMapClick) } } }) } ੉ ௏٘ܳ хऱࢲ NaverMap੉ۄח Composableਸ ٜ݅ ࣻ ੓णפ׮
  53. @Composable fun NaverMap( modifier: Modifier = Modifier, mapOptions: NaverMapOptions =

    ..., mapProperties: MapProperties = ..., onMapClick: (PointF, LatLng) -> Unit = { _, _ -> }, ) { val savedInstanceState = rememberSavedInstanceState() val mapView = rememberMapViewWithLifecycle(savedInstanceState, mapOptions) AndroidView(factory = { mapView.apply { coroutineScope.launch { val naverMap = awaitMap() naverMap.mapType = mapProperties.mapType naverMap.isNightModeEnabled = mapProperties.isNightModeEnabled naverMap.setOnMapClickListener(onMapClick) } } }) } NaverMap( mapOptions = naverMapOptions(), mapProperties = MapProperties( mapType = NaverMap.MapType.Navi, isNightModeEnabled = true, ), onMapClick = { _, _ -> /* Do domething*/ } ) ࢎਊೞח ௏٘ ৘दੑפ׮ Ӓۢ ࢶ঱ഋ UIܳ ҳഅ೮׮Ҋ ೡ ࣻ ੓ਸөਃ?
  54. @Composable fun NaverMap( modifier: Modifier = Modifier, mapOptions: NaverMapOptions =

    ..., mapProperties: MapProperties = ..., onMapClick: (PointF, LatLng) -> Unit = { _, _ -> }, ) { val savedInstanceState = rememberSavedInstanceState() val mapView = rememberMapViewWithLifecycle(savedInstanceState, mapOptions) AndroidView(factory = { mapView.apply { coroutineScope.launch { val naverMap = awaitMap() naverMap.mapType = mapProperties.mapType naverMap.isNightModeEnabled = mapProperties.isNightModeEnabled naverMap.setOnMapClickListener(onMapClick) } } }) } 🤔 ࢚కо ߸҃ػ׮ݶ? 🫠 Recompositionীࢲ factoryח ׮द ഐ୹غ૑ ঋח׮. updateীࢲ јनೡ ࣻח ੓૑݅, ݒߣ side-e ff ectܳ ݅٘ח ޙઁ.
  55. Library۽ ҕਊചೞӝ Link: h tt ps://github.com/fornewid/naver-map-compose ૑Әө૑ ੘ࢿೠ ௏٘ח ೞա੄

    জীࢲ ࢎਊೞӝীח ୽࠙೮૑݅, ۄ੉࠳۞ܻ۽ ٜ݅ٸח ҕਊചػ ਬૉா੉झী ݏ୾ࢲ ੘ࢿ೧ঠѷભ? Ӓېࢲ ੉ߣীח খীࢲ ҳഅ೮؍ 5о૑ ਬૉா੉झܳ ѐࢶ೧ࠁ۰Ҋ ೤פ׮
  56. ૑ب ࠁৈ઱ӝ ✅ NaverMap(...) ੉ ࠗ࠙਷ ௼ѱ Ҋச ࠗ࠙੉ হ੉

    ইө ੘ࢿ೮؍ ௏ٜ٘ਸ Ӓ؀۽ ࢎਊೞݶ ؾפ׮
  57. ૑ب ২࣌ @Composable fun NaverMap(properties: MapProperties = ...) { ...

    AndroidView(factory = { mapView.apply { coroutineScope.launch { val naverMap = awaitMap() naverMap.mapType = properties.mapType naverMap.isNightModeEnabled = properties.isNightModeEnabled } } }) ইө ੘ࢿ೮؍ NaverMap ё୓ী mapType ١ਸ ࢸ੿ೞח ௏٘ੑפ׮
  58. ૑ب ২࣌ @Composable fun NaverMap(properties: MapProperties = ...) { ...

    AndroidView(factory = { mapView }) LaunchedEffect(Unit) { val naverMap = mapView.awaitMap() naverMap.mapType = properties.mapType naverMap.isNightModeEnabled = properties.isNightModeEnabled } } Side-effect APIੋ LaunchedEffectܳ ੉ਊ೧ࢲ Compositionীࢲ݅ ഐ୹غب۾ ߸҃ೡ ࣻ ੓णפ׮ ੉۞ݶ Recompositionীࢲח ׮द ࢸ੿غ૑ ঋѷભ
  59. ૑ب ২࣌ @Composable fun NaverMap(properties: MapProperties = ...) { ...

    AndroidView(factory = { mapView }) LaunchedEffect(Unit) { val naverMap = mapView.awaitMap() naverMap.mapType = properties.mapType naverMap.isNightModeEnabled = properties.isNightModeEnabled } } prope rt iesо ߸҃غযب ߈৔غ૑ ঋח ޙઁ. ೞ૑݅ propertiesо ߸҃غযب ߈৔غ૑ ঋח ޙઁо ࢤӤפ׮
  60. ૑ب ২࣌ @Composable fun NaverMap(properties: MapProperties = ...) { ...

    AndroidView(factory = { mapView }) val currentProperties by rememberUpdatedState(properties) LaunchedEffect(Unit) { val naverMap = mapView.awaitMap() naverMap.mapType = currentProperties.mapType naverMap.isNightModeEnabled = currentProperties.isNightModeEnabled } } Link: h tt ps://developer.android.com/jetpack/compose/side-e ff ects#rememberupdatedstate rememberUpdatedState۽ propertiesܳ хऱࢲ ੹׳ೞݶ ݃૑݄ী ੹׳߉਷ propertiesী ੽Ӕೡ ࣻ ੓णפ׮
  61. rememberUpdatedState ч੉ ߸҃غযب ੤द੘ೞ૑ ঋইঠ ೞח ബҗ੄ чਸ ଵઑೡ ٸ

    ࢎਊೠ׮. Source: h tt ps://medium.com/mobile-app-development-publication/a4867f876928
  62. ૑ب ২࣌ val currentProperties by rememberUpdatedState(properties) LaunchedEffect(Unit) { val naverMap

    = mapView.awaitMap() naverMap.mapType = currentProperties.mapType naverMap.isNightModeEnabled = currentProperties.isNightModeEnabled } ௏٘۽ ׮द جইоࠇद׮ ੉ ௏٘ীࢲ side-effectо ߊࢤೞח द੼੉ হભ?
  63. ૑ب ২࣌ val currentProperties by rememberUpdatedState(properties) val parentComposition = rememberCompositionContext()

    LaunchedEffect(Unit) { val naverMap = mapView.awaitMap() val composition = Composition(MapApplier(naverMap), parentComposition).apply { setContent { MapUpdater(mapProperties = currentProperties) } } try { awaitCancellation() } finally { composition.dispose() } } ࣁࠗ੸ੋ ࠗ࠙੉ ࡅ઎חؘ, पઁ۽ח ੉ۧѱ ੘ࢿ೮णפ׮
  64. ૑ب ২࣌ val currentProperties by rememberUpdatedState(properties) val parentComposition = rememberCompositionContext()

    LaunchedEffect(Unit) { val naverMap = mapView.awaitMap() val composition = Composition(MapApplier(naverMap), parentComposition).apply { setContent { MapUpdater(mapProperties = currentProperties) } } try { awaitCancellation() } finally { composition.dispose() } } Link: h tt ps://developer.android.com/reference/kotlin/androidx/compose/runtime/#Composition ࢜۽਍ Compositionਸ द੘ೞח ߑߨ. rememberCompositionContext۽ parentCompositionਸ ٜ݅Ҋ Compositionਵ۽ child compositionਸ ٜ݅঻णפ׮ setContent উীࢲח Composableਸ ࢶ঱ೡ ࣻ ੓Ҋ, ݽف ՘աݶ disposeܳ ഐ୹೤פ׮
  65. ૑ب ২࣌ val currentProperties by rememberUpdatedState(properties) val parentComposition = rememberCompositionContext()

    LaunchedEffect(Unit) { val naverMap = mapView.awaitMap() val composition = Composition(MapApplier(naverMap), parentComposition).apply { setContent { MapUpdater(mapProperties = currentProperties) } } try { awaitCancellation() } finally { composition.dispose() } } Link: h tt ps://developer.android.com/reference/kotlin/androidx/compose/runtime/Applier ૑ب ࣘࢿਸ Composable উীࢲ ҙܻೠ׮. ૑ب ࣘࢿ਷ MapUpdaterۄח Composable উীࢲ ҙܻೞҳਃ Child Compositionਸ ࢤࢿೡ ٸ, Composable Treeܳ ҙܻೞח Applierܳ ֍णפ׮
  66. MapApplierח Composition ઺ী MapNode ౟ܻܳ ҙܻೞח ৉ೡ. MapUpdaterח ૑ب ࣘࢿਸ

    ҙܻೞח ComposeNodeܳ ࢤࢿೠ׮. MapUpdater NaverMap MapApplier, MapUpdater MapApplier MapPropertiesNode Listeners getMap() MapNode MapNode MapNode = ComposeNode NaverMap @Composable @Composable
  67. MapApplier class MapApplier( val map: NaverMap, ) : AbstractApplier<MapNode>(MapNodeRoot) {

    private val decorations = mutableListOf<MapNode>() ... } interface MapNode object MapRootNode : MapNode class MapPropertiesNode(val map: NaverMap) : MapNode MapApplierীࢲ MapNode Listܳ ҙܻೞҊ, MapNode ҳഅ୓ ઺ী MapPropertiesNodeо ੓णפ׮
  68. MapUpdater @Composable fun MapUpdater(mapProperties: MapProperties) { val map = (currentComposer.applier

    as MapApplier).map ComposeNode<MapPropertiesNode, MapApplier>( factory = { MapPropertiesNode(map = map) }, update = { set(mapProperties.mapType) { map.mapType = it.value } set(mapProperties.isNightModeEnabled) { map.isNightModeEnabled = it } } ) Link: h tt ps://developer.android.com/reference/kotlin/androidx/compose/runtime/#ComposeNode MapPropertiesNodeח MapUpdater Composable ղࠗীࢲ ComposeNode APIܳ ੉ਊ೧ࢲ ࢤࢿೞҳਃ AndroidView API୊ۢ factoryীࢲ ࢤࢿ, updateীࢲ јन೧઱ח ഋక۽ غয ੓णפ׮
  69. MapProperties data class MapProperties( public val mapType: MapType = MapType.Basic,

    public val isNightModeEnabled: Boolean = false, ) @Immutable enum class MapType( public val value: com.naver.maps.map.NaverMap.MapType ) { Basic(com.naver.maps.map.NaverMap.MapType.Basic), ... } Link: h tt ps://medium.com/androiddevelopers/jetpack-compose-stability-explained-79c10db270c8 MapPropertiesח mapType э਷ ૑ب੄ ࣘࢿҗ ݒடغח data classੑפ׮ ৈӝࢲ MapType਷ ֎੉ߡ૑ب SDK੄ MapTypeਸ хऱח ഋక۽ غয ੓חؘਃ
  70. MapProperties data class MapProperties( public val mapType: MapType = MapType.Basic,

    public val isNightModeEnabled: Boolean = false, ) @Immutable enum class MapType( public val value: com.naver.maps.map.NaverMap.MapType ) { Basic(com.naver.maps.map.NaverMap.MapType.Basic), ... } Link: h tt ps://medium.com/androiddevelopers/jetpack-compose-stability-explained-79c10db270c8 Compose ஹ౵ੌ۞о प೯غ૑ ঋח ݽٕ੄ ௿ېझח ࠛউ੿ೠ Ѫਵ۽ ୶ۿػ׮. wrapper classী ࠛ߸ਸ ੿੄ೞৈ Recompositionਸ ୭ࣗചೡ ࣻ ੓׮. Ӓ ੉ਬח, ֎੉ߡ૑ب SDKח Compose ஹ౵ੌ۞о प೯غ૑ ঋই Composeীࢲח ੉۠ ௿ېझܳ unstable۽ ୶ۿೞӝ ٸޙੑפ׮ @immutableਸ ୶оೞৈ ࠛ೙ਃೠ recompositionਸ ઴ੌ ࣻ ੓णפ׮
  71. ૑ب ২࣌ ✅ NaverMap( ... mapProperties = MapProperties( mapType =

    NaverMap.MapType.Navi, isNightModeEnabled = true, ), ... ) ૑ب ২࣌ਸ ࢚క۽ ੹׳ೞח ࠗ࠙ਸ ৮ࢿ೮णפ׮
  72. ૑ب ২࣌ @Composable fun NaverMap(properties: MapProperties = ...) { ...

    val currentProperties by rememberUpdatedState(properties) val parentComposition = rememberCompositionContext() LaunchedEffect(Unit) { val naverMap = mapView.awaitMap() val composition = Composition( MapApplier(naverMap), parentComposition ).apply { setContent { MapUpdater(mapProperties = currentProperties) } } ߑӘө૑ ࠄ ૑ب ২࣌ ௏٘۽, propertiesܳ ੹׳೧઱ח ࠗ࠙ਸ ੘ࢿ೮חؘਃ
  73. ૑ب ੉߮౟ @Composable fun NaverMap(onMapClick: (PointF, LatLng) -> Unit =

    { _, _ -> }) { ... val mapClickListeners = remember { MapClickListeners() } .also { it.onMapClick = onMapClick } val parentComposition = rememberCompositionContext() LaunchedEffect(Unit) { val naverMap = mapView.awaitMap() val composition = Composition( MapApplier(naverMap), parentComposition ).apply { setContent { MapUpdater(clickListeners = mapClickListeners) } } ૑ب ੉߮౟ীࢲח onMapClick੉ۄח ۈ׮ܳ ੹׳೤פ׮
  74. ૑ب ੉߮౟ @Composable fun NaverMap(onMapClick: (PointF, LatLng) -> Unit =

    { _, _ -> }) { ... val mapClickListeners = remember { MapClickListeners() } .also { it.onMapClick = onMapClick } val parentComposition = rememberCompositionContext() LaunchedEffect(Unit) { val naverMap = mapView.awaitMap() val composition = Composition( MapApplier(naverMap), parentComposition ).apply { setContent { MapUpdater(clickListeners = mapClickListeners) } } class MapClickListeners { var onMapClick: (PointF, LatLng) -> Unit by mutableStateOf({ _, _ -> }) } MapClickListenersח onMapClick ۈ׮ܳ MutableState۽ ҙܻೞҊ, recompositionীࢲ MapClickListenersо ߄Շ૑ ঋب۾ remember۽ ӝর೧સפ׮
  75. ૑ب ੉߮౟ @Composable fun NaverMap(onMapClick: (PointF, LatLng) -> Unit =

    { _, _ -> }) { ... val mapClickListeners = remember { MapClickListeners() } .also { it.onMapClick = onMapClick } val parentComposition = rememberCompositionContext() LaunchedEffect(Unit) { val naverMap = mapView.awaitMap() val composition = Composition( MapApplier(naverMap), parentComposition ).apply { setContent { MapUpdater(clickListeners = mapClickListeners) } } Ӓېࢲ MapUpdater ղࠗীࢲ ੉߮౟о ߊࢤೞݶ ੉۠ ࣽࢲ۽ ੉߮౟о ࢚ਤ۽ ੹౵ؾפ׮
  76. // Composition ૑ب ੉߮౟ @Composable fun MapUpdater(clickListeners: MapClickListeners) { ComposeNode<MapPropertiesNode,

    MapApplier>( factory = { MapPropertiesNode(clickListeners = clickListeners) }, update = { update(clickListeners) { this.clickListeners = it } }, ) } class MapPropertiesNode( var map: NaverMap, var clickListeners: MapClickListeners, ) : MapNode { override fun onAttached() { map.setOnMapClickListener { point, coord -> clickListeners.onMapClick(point, coord) } } MapUpdaterীࢲח Composition द੼ী clickListenersܳ ੹׳೧઱Ҋ
  77. // Recomposition ૑ب ੉߮౟ @Composable fun MapUpdater(clickListeners: MapClickListeners) { ComposeNode<MapPropertiesNode,

    MapApplier>( factory = { MapPropertiesNode(clickListeners = clickListeners) }, update = { update(clickListeners) { this.clickListeners = it } }, ) } class MapPropertiesNode( var map: NaverMap, var clickListeners: MapClickListeners, ) : MapNode { override fun onAttached() { map.setOnMapClickListener { point, coord -> clickListeners.onMapClick(point, coord) } } Recomposition द੼ীח ۈ׮о ߄Շ঻ਸ ࣻ ੓ਵפ MapClickListenersܳ ׮द Ү୓೧સפ׮
  78. ૑ب ੉߮౟ @Composable fun MapUpdater(clickListeners: MapClickListeners) { ComposeNode<MapPropertiesNode, MapApplier>( factory

    = { MapPropertiesNode(clickListeners = clickListeners) }, update = { update(clickListeners) { this.clickListeners = it } }, ) } class MapPropertiesNode( var map: NaverMap, var clickListeners: MapClickListeners, ) : MapNode { override fun onAttached() { map.setOnMapClickListener { point, coord -> clickListeners.onMapClick(point, coord) } } MapPropertiesNodeо attachغݶ NaverMapী Listenerܳ ١۾೤פ׮
  79. ૑ب ੉߮౟ @Composable fun MapUpdater(clickListeners: MapClickListeners) { ComposeNode<MapPropertiesNode, MapApplier>( factory

    = { MapPropertiesNode(clickListeners = clickListeners) }, update = { update(clickListeners) { this.clickListeners = it } }, ) } class MapPropertiesNode( var map: NaverMap, var clickListeners: MapClickListeners, ) : MapNode { override fun onAttached() { map.setOnMapClickListener { point, coord -> clickListeners.onMapClick(point, coord) } } ֎੉ߡ૑بীࢲ ੉߮౟о ߊࢤೞݶ ੉۠ ࣽਵ۽ ࢚ਤ۽ ੹౵ؾפ׮
  80. ૑ب ੉߮౟ ✅ NaverMap( ... onMapClick = { _, _

    -> /* Do domething*/ } ... ) ੉ۧѱ ֎੉ߡ૑بীࢲ ੉߮౟ܳ ׮ܖח ࠗ࠙ب ҳഅ೧ࠌणפ׮
  81. // State ݃ழ val marker = Marker().apply { captionText =

    "caption" position = LatLng(..., ...) icon = OverlayImage.fromResource(R.drawable.marker_icon) setOnClickListener { ... true } map = naverMap } ੉ۧѱ ࢚కܳ ੿੄ೞח ࠗ࠙੉ ੓Ҋ
  82. // Event ݃ழ val marker = Marker().apply { captionText =

    "caption" position = LatLng(..., ...) icon = OverlayImage.fromResource(R.drawable.marker_icon) setOnClickListener { ... true } map = naverMap } ੉߮౟ী ؀ೠ ࠗ࠙੉ ੓Ҋ
  83. // Display ݃ழ val marker = Marker().apply { captionText =

    "caption" position = LatLng(..., ...) icon = OverlayImage.fromResource(R.drawable.marker_icon) setOnClickListener { ... true } map = naverMap } ֎੉ߡ૑بী ࠁৈ઱ח ࠗ࠙੉ ੓णפ׮
  84. ݃ழ Marker( captionText = "caption", position = LatLng(..., ...), icon

    = OverlayImage.fromResource(R.drawable.marker_icon), onClick = { ... true }, ) Composeীࢲח ੉۠ ഋక۽ ࢎਊೡ ࣻ ੓ѱ ٜ݅঻णפ׮
  85. ݃ழ Marker( captionText = "caption", position = LatLng(..., ...), icon

    = OverlayImage.fromResource(R.drawable.marker_icon), onClick = { ... true }, ) @Composable fun Marker( captionText: String? = ..., position: LatLng = ..., icon: OverlayImage = ..., onClick: (Marker) -> Boolean = { false }, ) { ... } ੉੹୊ۢ ComposeNodeܳ ഝਊ೧ࢲ Marker Composableਸ ٜ݅ݶ ؾפ׮
  86. ComposeNodeܳ ࢤࢿೞৈ ࢚కܳ সؘ੉౟. MapApplierܳ ా೧ ૑بী ಴दೠ׮. Marker NaverMap

    Marker ҳઑ MapApplier MarkerNode Marker onClick getMap() MapNode MapNode MapNode = ComposeNode NaverMap @Composable @Composable Link: h tt ps://github.com/fornewid/naver-map-compose/.../com/naver/maps/map/compose/Marker.kt
  87. ݃ழ Marker( captionText = "caption", position = LatLng(..., ...), icon

    = OverlayImage.fromResource(R.drawable.marker_icon), onClick = { ... true }, ) // map = naverMap ? NaverMapী ಴द೧઱ח ࠗ࠙਷ ௏٘۽ যڌѱ ಴അೞݶ જਸөਃ?
  88. ݃ழ NaverMap(...) { Marker( captionText = "caption", position = LatLng(...,

    ...), icon = OverlayImage.fromResource(R.drawable.marker_icon), onClick = { ... true }, ) } ੉ۧѱ NaverMap Composable ղࠗী Child Composable۽ ࢶ঱೧઱ݶ ؾפ׮
  89. Example: ӓ੢ ݃ழ ҙܻೞӝ var markers by remember { mutableStateOf<List<Marker>>(emptyList())

    } LaunchedEffect(theaters) { val naverMap = mapView.awaitMap() markers.forEach { it.map = null } markers = theaters.map { theater -> Marker().apply { ... map = naverMap } } } ష੉ ೐۽ં౟ীࢲ ੘ࢿ೮؍ ௏٘ח UIܳ Side-effect۽ ҙܻೞח ו՝੉঻חؘਃ
  90. Example: ӓ੢ ݃ழ ҙܻೞӝ NaverMap(...) { theaters.forEach { theater ->

    Marker( ... ) } } ੉ઁ ખ ؊ ࢶ঱ഋ UIী оӰѱ ݃ழܳ ಴दೡ ࣻ ੓णפ׮
  91. ݃ழ ࠁৈ઱ӝ ✅ NaverMap { Marker( position = LatLng(..., ...),

    ... onClick = { /* Do domething*/ true }, ) }
  92. Use Case 5: ஠ݫۄ ੉ز Con fi g Changes द੼ী

    ࢚కܳ ਬ૑ೡ ࣻ হਸө? rememberSaveable
  93. ஠ݫۄী ؀ೠ ࢚క, ੉߮౟ܳ ҙܻೞח State Holder. MapUpdater CameraPositionState NaverMap

    MapPropertiesNode CameraPositionState CameraPosition NaverMap Listeners Composition only State Holder Event New CameraPosition @Composable Compositionীࢲ݅ ݃૑݄ী ੷੢ೠ ਤ஖۽ ஠ݫۄܳ ੉ز೤פ׮
  94. internal class MapPropertiesNode( val map: NaverMap, cameraPositionState: CameraPositionState, ) :

    MapNode { init { cameraPositionState.setMap(map) } private val cameraIdleListener = NaverMap.OnCameraIdleListener { cameraPositionState.rawPosition = map.cameraPosition } private val cameraChangeListener = NaverMap.OnCameraChangeListener { _, _ -> cameraPositionState.rawPosition = map.cameraPosition } override fun onAttached() { map.addOnCameraIdleListener(cameraIdleListener) map.addOnCameraChangeListener(cameraChangeListener) } } MapPropertiesNode ௏٘ܳ ࢓ಝࠇद׮
  95. internal class MapPropertiesNode( val map: NaverMap, cameraPositionState: CameraPositionState, ) :

    MapNode { init { cameraPositionState.setMap(map) } private val cameraIdleListener = NaverMap.OnCameraIdleListener { cameraPositionState.rawPosition = map.cameraPosition } private val cameraChangeListener = NaverMap.OnCameraChangeListener { _, _ -> cameraPositionState.rawPosition = map.cameraPosition } override fun onAttached() { map.addOnCameraIdleListener(cameraIdleListener) map.addOnCameraChangeListener(cameraChangeListener) } } cameraPositionStateী NaverMap ё୓ܳ ࢸ੿೧઱Ҋ Listenerܳ ా೧, ߄Ո ஠ݫۄ ਤ஖о ٜযয়ݶ rawPositionਸ সؘ੉౟ ೧સפ׮
  96. public class CameraPositionState(position: CameraPosition = ...) { internal var rawPosition

    by mutableStateOf(position) public var position: CameraPosition get() = rawPosition set(value) { ... } internal fun setMap(map: NaverMap?) { this.map = map if (map != null) { map.moveCamera(CameraUpdate.toCameraPosition(position)) } } } NaverMap੉ ׮द ࢸ੿غݶ(=Composition), ݃૑݄ ਤ஖۽ ੉زೠ׮. NaverMap੉ ׮द ࢸ੿غݶ Compositionਵ۽ ౸ױೞҊ, ݃૑݄ ਤ஖۽ ੉زदெ઱ח ୊ܻо ٜযо ੓णפ׮
  97. @Composable public inline fun rememberCameraPositionState( key: String? = null, crossinline

    init: CameraPositionState.() -> Unit = {}, ): CameraPositionState = rememberSaveable( key = key, saver = CameraPositionState.Saver ) { CameraPositionState().apply(init) } public val Saver: Saver<CameraPositionState, CameraPosition> = Saver( save = { it.position }, restore = { CameraPositionState(it) } ) Con fi g Changes द੼ী ݃૑݄ ࢚కܳ ੷੢೧ળ׮. Link: h tt ps://developer.android.com/jetpack/compose/state#restore-ui-state rememberSaveableܳ ੉ਊ೧ࢲ Config Changes द੼ী ݃૑݄ ࢚కܳ ੷੢/ࠂҳ ೧સפ׮
  98. val cameraPositionState = rememberCameraPositionState() NaverMap(cameraPositionState = cameraPositionState) val coroutineScope =

    rememberCoroutineScope() coroutineScope.launch { cameraPositionState.animate( CameraUpdate.scrollTo(position), animation = CameraAnimation.Fly, durationMs = 1_000 ) } ஠ݫۄ ੉ز ✅ ࢎਊೡ ٸח NaverMap Composableী State Holderܳ ੹׳೧઱Ҋ ੉زೡ ٸח ௏ܖ౯ਸ ੉ਊೞৈ গפݫ੉࣌ ୊ܻܳ ೡ ࣻ ੓णפ׮
  99. • Composable Lifecycle - Composition - Recomposition • Architecture -

    Unidirectional Data Flow - State Holder • State - remember - rememberSaveable - mutableStateOf - @Immutable Keywords • Side-effects - LaunchedEffect - DisposableEffect - rememberCoroutineScope - rememberUpdatedState • Interoperability APIs - AndroidView - setContent • Custom Composition - rememberCompositionContext - Composition - Applier, ComposeNode