Skip to content

Commit

Permalink
경북대 Android_유지예_5주차과제_Step1 (#47)
Browse files Browse the repository at this point in the history
* docs:readme.md

* feat: step0 code upload with package, mocking

* docs: readme.md

* build: dependencies & settings

* feat: MyApplication - Hilt

* feat: mapitem - room db

* feat: dao define

* feat: room database

* feat: hilt app module

* feat: MapRepository abstracton

* feat: ViewModel

* feat: ui - main, search

* fix: api key

로컬에서는 수정해두었는데 반영되지 않은 브랜치로 pr을 올린 거 같습니다. 다음부턴 주의하겠습니다.

---------

Co-authored-by: 유지예 <[email protected]>
  • Loading branch information
YJY1220 and 유지예 authored Jul 28, 2024
1 parent c9d8ff5 commit 5719de7
Show file tree
Hide file tree
Showing 14 changed files with 151 additions and 84 deletions.
12 changes: 11 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,14 @@
# android-map-refactoring
### KakaoTechCampus 2기 Step2 - 5주차 과제 : 리팩토링

### 0단계. 4주차 코드 반영하기
### 1단계. 의존성 주입

### 기능 구현
- [ ] build 파일 의존성 추가
- [ ] Hilt 의존성 적용한 MyApplication 구현
- [ ] Room Database 정의
- [ ] DAO 정의
- [ ] Room Database와 DAO에 Hilt 모듈 설정 구현
- [ ] 데이터 추상화 구현
- [ ] ViewModel 및 UI hilt 의존성 및 room 적용 수정

33 changes: 21 additions & 12 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ fun getApiKey(key: String): String {
plugins {
id("com.android.application")
id("org.jetbrains.kotlin.android")
id("org.jetbrains.kotlin.kapt")
id("dagger.hilt.android.plugin")
}

android {
Expand All @@ -21,10 +23,9 @@ android {
targetSdk = 34
versionCode = 1
versionName = "1.0"

testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"

//API 가져오기

resValue("string", "kakao_api_key", getApiKey("KAKAO_API_KEY"))
buildConfigField("String", "KAKAO_REST_API_KEY", "\"${getApiKey("KAKAO_REST_API_KEY")}\"")
}
Expand Down Expand Up @@ -65,9 +66,14 @@ dependencies {
implementation("com.squareup.retrofit2:retrofit:2.9.0")
implementation("com.squareup.retrofit2:converter-gson:2.9.0")
implementation("com.squareup.okhttp3:logging-interceptor:4.9.0")
implementation("com.kakao.sdk:v2-user:2.10.0") // Kakao SDK 추가
implementation("com.kakao.sdk:v2-user:2.10.0")
implementation("com.kakao.maps.open:android:2.9.5")
implementation("androidx.activity:activity:1.8.0")
implementation("androidx.room:room-runtime:2.5.0")
kapt("androidx.room:room-compiler:2.5.0")
implementation("androidx.room:room-ktx:2.5.0")
implementation("com.google.dagger:hilt-android:2.46.1")
kapt("com.google.dagger:hilt-compiler:2.46.1")
testImplementation("junit:junit:4.13.2")
androidTestImplementation("androidx.test.ext:junit:1.1.5")
androidTestImplementation("androidx.test.espresso:espresso-core:3.5.1")
Expand All @@ -76,13 +82,16 @@ dependencies {
implementation("androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1")
implementation("com.google.android.gms:play-services-maps:19.0.0")
implementation("com.google.android.material:material:1.11.0")
testImplementation ("junit:junit:4.13.2")
androidTestImplementation ("androidx.test.ext:junit:1.1.3")
androidTestImplementation ("androidx.test.espresso:espresso-core:3.4.0")
androidTestImplementation ("androidx.test:core-ktx:1.4.0")
androidTestImplementation ("androidx.test:runner:1.4.0")
androidTestImplementation ("androidx.test:rules:1.4.0")
androidTestImplementation ("org.mockito:mockito-core:3.11.2")
androidTestImplementation ("org.mockito:mockito-android:3.11.2")
androidTestImplementation ("androidx.arch.core:core-testing:2.1.0")
androidTestImplementation("androidx.test:core-ktx:1.4.0")
androidTestImplementation("androidx.test:runner:1.4.0")
androidTestImplementation("androidx.test:rules:1.4.0")
androidTestImplementation("org.mockito:mockito-core:3.11.2")
androidTestImplementation("org.mockito:mockito-android:3.11.2")
androidTestImplementation("androidx.arch.core:core-testing:2.1.0")
}

afterEvaluate {
kapt {
correctErrorTypes = true
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ import androidx.test.platform.app.InstrumentationRegistry
import campus.tech.kakao.map.model.MapItem
import campus.tech.kakao.map.repository.MapRepository
import campus.tech.kakao.map.viewmodel.MapViewModel
import campus.tech.kakao.map.viewmodel.MapViewModelFactory
import campus.tech.kakao.map.R
import campus.tech.kakao.map.ui.MainActivity
import campus.tech.kakao.map.ui.SearchActivity
Expand Down
3 changes: 3 additions & 0 deletions app/src/main/java/campus/tech/kakao/MyApplication.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@ package campus.tech.kakao
import android.app.Application
import campus.tech.kakao.map.R
import com.kakao.vectormap.KakaoMapSdk
import dagger.hilt.android.HiltAndroidApp

@HiltAndroidApp

class MyApplication : Application() {
override fun onCreate() {
Expand Down
16 changes: 16 additions & 0 deletions app/src/main/java/campus/tech/kakao/map/dao/MapItemDao.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package campus.tech.kakao.map.database

import androidx.room.Dao
import androidx.room.Insert
import androidx.room.Query
import campus.tech.kakao.map.model.MapItem

@Dao
interface MapItemDao {

@Insert
suspend fun insert(mapItem: MapItem)

@Query("SELECT * FROM MapItem WHERE place_name LIKE :query")
suspend fun searchItems(query: String): List<MapItem>
}
10 changes: 10 additions & 0 deletions app/src/main/java/campus/tech/kakao/map/database/AppDatabase.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package campus.tech.kakao.map.database

import androidx.room.Database
import androidx.room.RoomDatabase
import campus.tech.kakao.map.model.MapItem

@Database(entities = [MapItem::class], version = 1, exportSchema = false)
abstract class AppDatabase : RoomDatabase() {
abstract fun mapItemDao(): MapItemDao
}
31 changes: 31 additions & 0 deletions app/src/main/java/campus/tech/kakao/map/di/AppModule.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package campus.tech.kakao.map.di

import android.content.Context
import androidx.room.Room
import campus.tech.kakao.map.database.AppDatabase
import campus.tech.kakao.map.database.MapItemDao
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent
import javax.inject.Singleton

@Module
@InstallIn(SingletonComponent::class)
object AppModule {

@Provides
@Singleton
fun provideDatabase(appContext: Context): AppDatabase {
return Room.databaseBuilder(
appContext,
AppDatabase::class.java,
"map_database"
).build()
}

@Provides
fun provideMapItemDao(database: AppDatabase): MapItemDao {
return database.mapItemDao()
}
}
8 changes: 5 additions & 3 deletions app/src/main/java/campus/tech/kakao/map/model/MapItem.kt
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
package campus.tech.kakao.map.model

//이름 보다 알기 쉽게 변경 - api맞춰서
import androidx.room.Entity
import androidx.room.PrimaryKey

@Entity(tableName = "MapItem")
data class MapItem(
val id: String,
@PrimaryKey val id: Int,
val place_name: String,
val road_address_name: String,
val category_group_name: String,
val x: Double,
val y: Double

)
Original file line number Diff line number Diff line change
@@ -1,17 +1,29 @@
package campus.tech.kakao.map.repository

import android.app.Application
import campus.tech.kakao.map.database.MapItemDao
import campus.tech.kakao.map.network.KakaoApiService
import campus.tech.kakao.map.model.MapItem
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import javax.inject.Inject

interface MapRepository {
suspend fun searchItems(query: String): List<MapItem>
}

class MapRepositoryImpl(private val application: Application) : MapRepository {

private val mapAccess = MapAccess(application)
class MapRepositoryImpl @Inject constructor(
private val mapItemDao: MapItemDao,
private val apiService: KakaoApiService
) : MapRepository {

override suspend fun searchItems(query: String): List<MapItem> {
return mapAccess.searchItems(query)
return withContext(Dispatchers.IO) {
val response = apiService.searchPlaces(Constants.KAKAO_API_KEY, query)
if (response.isSuccessful) {
response.body()?.documents ?: emptyList()
} else {
emptyList()
}
}
}
}
}
57 changes: 18 additions & 39 deletions app/src/main/java/campus/tech/kakao/map/ui/MainActivity.kt
Original file line number Diff line number Diff line change
@@ -1,41 +1,34 @@
package campus.tech.kakao.map.ui


import android.app.Activity
import android.content.Context
import android.content.Intent
import android.os.Bundle
import android.util.Log

import android.widget.EditText
import androidx.appcompat.app.AppCompatActivity
import com.kakao.vectormap.MapView
import com.kakao.vectormap.MapLifeCycleCallback
import com.kakao.vectormap.KakaoMapReadyCallback
import com.kakao.vectormap.KakaoMap

import android.view.View
import android.widget.EditText
import android.widget.FrameLayout
import android.widget.ImageButton
import android.widget.RelativeLayout
import android.widget.TextView
import android.app.Activity
import android.widget.FrameLayout
import campus.tech.kakao.map.viewmodel.MapViewModelFactory
import androidx.activity.viewModels
import androidx.appcompat.app.AppCompatActivity
import com.google.android.material.bottomsheet.BottomSheetBehavior
import com.kakao.vectormap.*
import campus.tech.kakao.map.R
import campus.tech.kakao.map.model.MapItem
import com.google.android.material.bottomsheet.BottomSheetBehavior
import com.kakao.vectormap.LatLng
import campus.tech.kakao.map.viewmodel.MapViewModel
import com.kakao.vectormap.camera.CameraAnimation
import com.kakao.vectormap.camera.CameraUpdateFactory
import com.kakao.vectormap.label.LabelLayer
import com.kakao.vectormap.label.LabelOptions
import com.kakao.vectormap.label.LabelStyle
import com.kakao.vectormap.label.LabelStyles
import com.kakao.vectormap.label.LabelTextStyle
import com.kakao.vectormap.camera.CameraAnimation
import com.kakao.vectormap.camera.CameraUpdateFactory

import dagger.hilt.android.AndroidEntryPoint

@AndroidEntryPoint
class MainActivity : AppCompatActivity() {

lateinit var viewModelFactory: MapViewModelFactory
private lateinit var mapView: MapView
private lateinit var errorLayout: RelativeLayout
private lateinit var errorMessage: TextView
Expand All @@ -48,8 +41,9 @@ class MainActivity : AppCompatActivity() {
private lateinit var bottomSheetAddress: TextView
private lateinit var bottomSheetLayout: FrameLayout
private var selectedItems = mutableListOf<MapItem>()

companion object {
private val viewModel: MapViewModel by viewModels()

companion object {
const val SEARCH_REQUEST_CODE = 1
const val PREFS_NAME = "LastMarkerPrefs"
const val PREF_LATITUDE = "lastLatitude"
Expand All @@ -58,7 +52,6 @@ class MainActivity : AppCompatActivity() {
const val PREF_ROAD_ADDRESS_NAME = "lastRoadAddressName"
}


override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
Expand All @@ -68,10 +61,11 @@ class MainActivity : AppCompatActivity() {
mapView.start(object : MapLifeCycleCallback() {
override fun onMapDestroy() {
// 지도 API가 정상적으로 종료될 때 호출됨
Log.d("MainActivity", "Map destroyed")
}

override fun onMapError(error: Exception) {

Log.e("MainActivity", "Map error: ${error.message}")
showErrorScreen(error)
}
}, object : KakaoMapReadyCallback() {
Expand All @@ -80,15 +74,13 @@ class MainActivity : AppCompatActivity() {
labelLayer = kakaoMap.labelManager?.layer!!
// 마지막 마커 위치 불러오기
loadLastMarkerPosition()

}
})

// 검색창 클릭 시 검색 페이지로 이동
val searchEditText = findViewById<EditText>(R.id.search_edit_text)
searchEditText.setOnClickListener {
val intent = Intent(this, SearchActivity::class.java)

intent.putExtra("selectedItemsSize", selectedItems.size)
selectedItems.forEachIndexed { index, mapItem ->
intent.putExtra("id_$index", mapItem.id)
Expand All @@ -115,18 +107,6 @@ class MainActivity : AppCompatActivity() {
bottomSheetLayout.visibility = View.GONE
}

// 지도 -> 검색페이지 돌아갈 때 저장된 검색어 목록 그대로 저장
private fun processIntentData() {
val placeName = intent.getStringExtra("place_name")
val roadAddressName = intent.getStringExtra("road_address_name")
val x = intent.getDoubleExtra("x", 0.0)
val y = intent.getDoubleExtra("y", 0.0)
if (placeName != null && roadAddressName != null) {
addLabel(placeName, roadAddressName, x, y)

}
}

override fun onResume() {
super.onResume()
mapView.resume() // MapView의 resume 호출
Expand All @@ -135,7 +115,6 @@ class MainActivity : AppCompatActivity() {
override fun onPause() {
super.onPause()
mapView.pause() // MapView의 pause 호출

}

fun showErrorScreen(error: Exception) {
Expand Down Expand Up @@ -177,7 +156,7 @@ class MainActivity : AppCompatActivity() {
selectedItems.clear()
val selectedItemsSize = it.getIntExtra("selectedItemsSize", 0)
for (i in 0 until selectedItemsSize) {
val id = it.getStringExtra("id_$i") ?: ""
val id = it.getIntExtra("id_$i",0)
val place_name = it.getStringExtra("place_name_$i") ?: ""
val road_address_name = it.getStringExtra("road_address_name_$i") ?: ""
val category_group_name = it.getStringExtra("category_group_name_$i") ?: ""
Expand Down
Loading

0 comments on commit 5719de7

Please sign in to comment.