Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

전남대 Android_이가현 5주차 step2 과제 #80

Open
wants to merge 14 commits into
base: leeghy
Choose a base branch
from
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
# android-map-location
# android-map-refactoring

0단계 ✅
- 코드 복사

1단계
1단계
- 데이터베이스를 Room으로 변경한다.
- 가능한 모든 부분에 대해서 의존성 주입을 적용한다.

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

val properties = Properties()
Expand Down Expand Up @@ -66,6 +68,9 @@ android {
viewBinding = true
buildConfig = true
}
hilt {
enableAggregatingTask = false
}
}

dependencies {
Expand All @@ -82,6 +87,12 @@ dependencies {
implementation("com.kakao.maps.open:android:2.9.5")
implementation("com.kakao.sdk:v2-all:2.20.3")
implementation("androidx.activity:activity:1.9.0")
implementation("androidx.room:room-common:2.6.1")
implementation("androidx.room:room-ktx:2.6.1")
implementation("com.google.dagger:hilt-android:2.48.1")
kapt("androidx.room:room-compiler:2.6.1")
kapt("com.google.dagger:hilt-compiler:2.48.1")


// 테스트 의존성 추가
testImplementation("junit:junit:4.13.2")
Expand All @@ -99,4 +110,7 @@ dependencies {
androidTestImplementation("androidx.test:rules:1.4.0")
androidTestImplementation("androidx.test:runner:1.4.0")
androidTestImplementation("androidx.arch.core:core-testing:2.1.0")

implementation("androidx.lifecycle:lifecycle-viewmodel-ktx:2.6.1")
implementation("androidx.lifecycle:lifecycle-livedata-ktx:2.6.1")
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import android.app.Application
import androidx.arch.core.executor.testing.InstantTaskExecutorRule
import campus.tech.kakao.map.Model.LocationData
import campus.tech.kakao.map.Model.Place
import campus.tech.kakao.map.Model.RetrofitClient
import campus.tech.kakao.map.Module.RetrofitClient
import campus.tech.kakao.map.Model.SearchResult
import campus.tech.kakao.map.viewmodel.DataDbHelper
import campus.tech.kakao.map.viewmodel.MainViewModel
Expand Down
52 changes: 30 additions & 22 deletions app/src/main/java/campus/tech/kakao/map/Adapter/LocationAdapter.kt
Original file line number Diff line number Diff line change
@@ -1,40 +1,48 @@
package campus.tech.kakao.map.Adapter

import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.ListAdapter
import androidx.recyclerview.widget.RecyclerView
import campus.tech.kakao.map.Model.LocationData
import campus.tech.kakao.map.R
import campus.tech.kakao.map.databinding.ItemViewBinding

class LocationAdapter(
private val locationList: List<LocationData>,
private val onItemViewClick: (LocationData) -> Unit
) : RecyclerView.Adapter<LocationAdapter.ViewHolder>() {
private val onItemClick: (LocationData) -> Unit
) : ListAdapter<LocationData, LocationAdapter.ViewHolder>(LocationDiffCallback()) {

class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
val nameTextView: TextView = itemView.findViewById(R.id.name)
val locationTextView: TextView = itemView.findViewById(R.id.location)
val categoryTextView: TextView = itemView.findViewById(R.id.category)
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
return ViewHolder(
ItemViewBinding.inflate(
LayoutInflater.from(parent.context),
parent,
false
)
Comment on lines +16 to +21

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

)
}

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val inflater = LayoutInflater.from(parent.context)
val view = inflater.inflate(R.layout.item_view, parent, false)
return ViewHolder(view)
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val location = getItem(position)
holder.bind(location)
holder.itemView.setOnClickListener { onItemClick(location) }

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

onBindViewHolder 시점에 setOnClickListener 는 성능이 좋지 않습니다. 안티패턴이에요.
holder 내부의 init 시점으로 옮겨주시는 편이 좋습니다.

ViewHolder 생성 시 onItemClick lambda 도 같이 추가하면 좋을 것 같네요 :)

}

override fun getItemCount(): Int = locationList.size
class ViewHolder(private val binding: ItemViewBinding) : RecyclerView.ViewHolder(binding.root) {
fun bind(location: LocationData) {
binding.name.text = location.name
binding.location.text = location.location
binding.category.text = location.category
}
}

override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val location = locationList[position]
holder.nameTextView.text = location.name
holder.locationTextView.text = location.location
holder.categoryTextView.text = location.category
private class LocationDiffCallback : DiffUtil.ItemCallback<LocationData>() {
override fun areItemsTheSame(oldItem: LocationData, newItem: LocationData): Boolean {
return oldItem.name == newItem.name
}

holder.itemView.setOnClickListener {
onItemViewClick(location)
override fun areContentsTheSame(oldItem: LocationData, newItem: LocationData): Boolean {
return oldItem == newItem
}
}
}
29 changes: 29 additions & 0 deletions app/src/main/java/campus/tech/kakao/map/Model/AppDatabase.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package campus.tech.kakao.map.Model

import android.content.Context
import androidx.room.Database
import androidx.room.Room
import androidx.room.RoomDatabase

@Database(entities = [LocationData::class], version = 1, exportSchema = false)
abstract class AppDatabase : RoomDatabase() {
abstract fun locationDao(): LocationDao

companion object {
private var instance: AppDatabase? = null

fun getInstance(context: Context): AppDatabase {
return instance ?: synchronized(this) {
instance ?: buildDatabase(context).also { instance = it }
}
}

private fun buildDatabase(context: Context): AppDatabase {
return Room.databaseBuilder(
context.applicationContext,
AppDatabase::class.java,
"location_database"
).build()
}
}
}
Original file line number Diff line number Diff line change
@@ -1,15 +1,12 @@
package campus.tech.kakao.map.Model

import retrofit2.Call
import retrofit2.http.GET
import retrofit2.http.Header
import retrofit2.http.Query

interface KakaoLocalApi {
@GET("v2/local/search/keyword.json")
fun searchPlaces(
@Header("Authorization") apiKey: String,
suspend fun searchPlaces(
@Query("query") query: String,
@Query("size") size: Int = 15
): Call<SearchResult>
): SearchResult
}
22 changes: 22 additions & 0 deletions app/src/main/java/campus/tech/kakao/map/Model/LocationDao.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package campus.tech.kakao.map.Model

import androidx.room.Dao
import androidx.room.Delete
import androidx.room.Insert
import androidx.room.OnConflictStrategy
import androidx.room.Query

@Dao
interface LocationDao {
@Query("SELECT * FROM locations")
fun getAllLocations(): List<LocationData>

@Insert(onConflict = OnConflictStrategy.REPLACE)
fun insertLocation(location: LocationData)

@Delete
fun deleteLocation(location: LocationData)

@Query("DELETE FROM locations")
fun deleteAllLocations()
}
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
package campus.tech.kakao.map.Model

import androidx.room.Entity
import androidx.room.PrimaryKey
import com.kakao.vectormap.LatLng

@Entity(tableName = "locations")
data class LocationData(
val name: String,
@PrimaryKey val name: String,
val location: String,
val category: String,
val latitude: Double,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@ import android.app.Application
import android.util.Log
import campus.tech.kakao.map.BuildConfig
import com.kakao.vectormap.KakaoMapSdk
import dagger.hilt.android.HiltAndroidApp

@HiltAndroidApp
class MyApplication: Application() {
override fun onCreate() {
super.onCreate()
Expand Down
17 changes: 0 additions & 17 deletions app/src/main/java/campus/tech/kakao/map/Model/RetrofitClient.kt

This file was deleted.

26 changes: 0 additions & 26 deletions app/src/main/java/campus/tech/kakao/map/Model/SearchCallback.kt

This file was deleted.

26 changes: 26 additions & 0 deletions app/src/main/java/campus/tech/kakao/map/Module/DatabaseModule.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package campus.tech.kakao.map.Module

import android.content.Context
import campus.tech.kakao.map.Model.AppDatabase
import campus.tech.kakao.map.Model.LocationDao
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.android.qualifiers.ApplicationContext
import dagger.hilt.components.SingletonComponent
import javax.inject.Singleton

@Module
@InstallIn(SingletonComponent::class)
object DatabaseModule {
@Provides
@Singleton
fun provideAppDatabase(@ApplicationContext context: Context): AppDatabase {
return AppDatabase.getInstance(context)
}

@Provides
fun provideLocationDao(database: AppDatabase): LocationDao {
return database.locationDao()
}
}
31 changes: 31 additions & 0 deletions app/src/main/java/campus/tech/kakao/map/Module/NetworkModule.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package campus.tech.kakao.map.Module

import campus.tech.kakao.map.Model.KakaoLocalApi
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory
import javax.inject.Singleton

@Module
@InstallIn(SingletonComponent::class)
object NetworkModule {
private const val BASE_URL = "https://dapi.kakao.com/"

@Provides
@Singleton
fun provideRetrofit(): Retrofit {
return Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.build()
}

@Provides
@Singleton
fun provideKakaoLocalApi(retrofit: Retrofit): KakaoLocalApi {
return retrofit.create(KakaoLocalApi::class.java)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package campus.tech.kakao.map.Repository

import campus.tech.kakao.map.Model.KakaoLocalApi
import campus.tech.kakao.map.Model.LocationData
import campus.tech.kakao.map.Model.LocationDao
import javax.inject.Inject

class LocationRepository @Inject constructor(
private val kakaoLocalApi: KakaoLocalApi,
private val locationDao: LocationDao
) {
suspend fun searchLocations(query: String): List<LocationData> {
return try {
val response = kakaoLocalApi.searchPlaces(query)
response.documents.map { place ->
LocationData(
name = place.place_name,
location = place.address_name,
category = place.category_group_name,
latitude = place.y.toDouble(),
longitude = place.x.toDouble()
)
}
} catch (e: Exception) {
// Log the error and return an empty list
e.printStackTrace()
emptyList()
}
}

suspend fun getAllLocations(): List<LocationData> {
return locationDao.getAllLocations()
}

suspend fun insertLocation(location: LocationData) {
locationDao.insertLocation(location)
}

suspend fun deleteLocation(location: LocationData) {
locationDao.deleteLocation(location)
}

suspend fun deleteAllLocations() {
locationDao.deleteAllLocations()
}
}
Loading