From 6aa7879439636bf77b517edaad2f78e8ad34788a Mon Sep 17 00:00:00 2001 From: aengzu <102356873+aengzu@users.noreply.github.com> Date: Sat, 27 Jul 2024 01:50:49 +0900 Subject: [PATCH] =?UTF-8?q?=EC=B6=A9=EB=82=A8=EB=8C=80=20Android=5F?= =?UTF-8?q?=EC=A0=84=EC=98=81=EC=A3=BC=205=EC=A3=BC=EC=B0=A8=20=EA=B3=BC?= =?UTF-8?q?=EC=A0=9C=20STEP=201=20(=ED=94=BC=EB=93=9C=EB=B0=B1=20=EB=B0=98?= =?UTF-8?q?=EC=98=81)=20(#30)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Initial commit * feat: step0 (#17) * 충남대Android_전영주_4주차 과제_Step1 (피드백 반영) (#37) * feat: step0 * docs: 1단계 기능 목록 작성 * feat(ui): create BottomSheet layout * feat: 마커 기능&바텀 시트 추가 * feat: 에러 화면 추가 * feat: 마지막 위치를 저장 및 앱 실행 시 포커스 * feat: 피드백 반영 * 충남대 Android_전영주 4주차 Step2 (#83) * feat: step0 * docs: 1단계 기능 목록 작성 * feat(ui): create BottomSheet layout * feat: 마커 기능&바텀 시트 추가 * feat: 에러 화면 추가 * feat: 마지막 위치를 저장 및 앱 실행 시 포커스 * feat: 피드백 반영 * feat: step2 UI테스트 코드 추가 * step0: 4주차 코드 가져오기 * feat: add Room entity annotation to DocumentEntity * feat: add SearchQueryEntity * refactor: restructure project folders * refactor: refactor to use Room and Hilt for DI - SearchQueryDao, VisitedPlaceDao 및 SearchQueryEntity, VisitedPlaceEntity 를 생성 - SharedPref 대신 Room 데이터베이스를 사용하도록 함 - 프로젝트 전반에 Hilt를 구현 - Hilt 사용을 위해 의존성 제공 모듈인 DatabaseModule, RepositoryModule, UsecaseModule 생성 - 메인 스레드 차단 방지를 위해 DB 작업은 백그라운드로 이동 - 원래 기능 별로 커밋하려 했으나 에러를 고치는 과정에서 다 연관되어 있어 한 번에 커밋합니다. ㅠ * fix: fix RecyclerView item click listener error - 아이템 클릭 리스너가 작동하지 않은 문제 해결 - 원인: XML 레이아웃 파일에 clickListener 바인딩이 누락됨 * fix: update search history order and prevent duplicate entries - 검색 기록 목록의 순서를 최신 검색이 가장 왼쪽에 오도록 변경했습니다.(reversed 사용) - 중복된 검색 기록이 추가되지 않도록 수정했습니다. * save the project * chore: recommit to correct previous commit * fix: 데이터 바인딩 관련 피드백 반영 * refactor: Update DI configuration for PlaceRepository and UseCases using Hilt - 기존에는 Provide 를 사용여서 의존성 주입을 하였으나 interface, Impl 을 @Binds 를 통해 bind 하는 방법으로 변경했습니다 - 비동기 작업 처리를 위해 repo Impl 에 디스패처 제공하였는데 object CoroutineDispatcherModule이 없으면 순환 참조 에러가 발생하여 이를 추가하였습니다. 이에 대한 추가적 공부를 주말에 해보겠습니다. * refactor: restructure project folders - data 패키지 내의 usecase 구현체를 domain 모듈로 이동했습니다 - API 서버로 부터 받게 되는 폴더를 entity 로 변경하고 로컬에서 데이터 전달 시 사용되는 domain 모듈 내의 model 을 dto 로 변경하였습니다 * refactor: add Qualifier for Database Name String injection - 데이터베이스 문자열 주입을 위해 @Qualifier 을 사용하였습니다 - 아직 잘 모르는 개념이라 시간이 부족하여 주말동안 더 조사해보겠습니다. * refactor: inject HttpService using Hilt - HttpService 도 의존성 주입을 사용하였습니다. - APIKey 와 BaseUrl 을 네트워크 모듈내에서 제공하여 HttpService 를 provide 하였습니다. * save the project --------- Co-authored-by: MyStoryG --- .../campus/tech/kakao/map/MapActivityTest.kt | 2 +- app/src/main/AndroidManifest.xml | 3 + .../campus/tech/kakao/map/MyApplication.kt | 8 ++ .../tech/kakao/map/data/PreferenceHelper.kt | 61 --------------- .../kakao/map/data/local/db/AppDatabase.kt | 12 +++ .../kakao/map/data/local/db/SearchQueryDao.kt | 21 ++++++ .../map/data/local/db/VisitedPlaceDao.kt | 15 ++++ .../data/local/entity/SearchQueryEntity.kt | 9 +++ .../data/local/entity/VisitedPlaceEntity.kt | 14 ++++ .../entity}/DocumentEntity.kt | 5 +- .../{model => remote/entity}/MetaEntity.kt | 2 +- .../entity}/SearchResponse.kt | 2 +- .../data/{ => remote}/network/HttpService.kt | 32 ++++---- .../{ => remote}/network/RetrofitObject.kt | 6 +- .../{ => remote}/network/RetrofitService.kt | 4 +- .../data/repository/PlaceRepositoryImpl.kt | 61 --------------- .../repositoryImpl/PlaceRepositoryImpl.kt | 75 +++++++++++++++++++ .../data/usecase/GetLastPlaceUseCaseImpl.kt | 13 ---- .../usecase/GetSearchHistoryUseCaseImpl.kt | 12 --- .../usecase/GetSearchPlacesUseCaseImpl.kt | 13 ---- .../usecase/RemoveSearchQueryUseCaseImpl.kt | 13 ---- .../data/usecase/SaveLastPlaceUseCaseImpl.kt | 13 ---- .../usecase/SaveSearchQueryUseCaseImpl.kt | 13 ---- .../kakao/map/di/CoroutineDispatcherModule.kt | 18 +++++ .../tech/kakao/map/di/DatabaseModule.kt | 41 ++++++++++ .../campus/tech/kakao/map/di/NetworkModule.kt | 34 +++++++++ .../tech/kakao/map/di/RepositoryModule.kt | 19 +++++ .../campus/tech/kakao/map/di/UsecaseModule.kt | 54 +++++++++++++ .../map/domain/{model => dto}/PlaceVO.kt | 2 +- .../map/domain/repository/PlaceRepository.kt | 14 ++-- .../map/domain/usecase/GetLastPlaceUseCase.kt | 4 +- .../domain/usecase/GetSearchHistoryUseCase.kt | 2 +- .../domain/usecase/GetSearchPlacesUseCase.kt | 4 +- .../usecase/RemoveSearchQueryUseCase.kt | 2 +- .../domain/usecase/SaveLastPlaceUseCase.kt | 4 +- .../domain/usecase/SaveSearchQueryUseCase.kt | 4 +- .../usecaseImpl/GetLastPlaceUseCaseImpl.kt | 13 ++++ .../GetSearchHistoryUseCaseImpl.kt | 12 +++ .../usecaseImpl/GetSearchPlacesUseCaseImpl.kt | 14 ++++ .../RemoveSearchQueryUseCaseImpl.kt | 13 ++++ .../usecaseImpl/SaveLastPlaceUseCaseImpl.kt | 13 ++++ .../usecaseImpl/SaveSearchQueryUseCaseImpl.kt | 14 ++++ .../kakao/map/presentation/MapActivity.kt | 23 ++---- .../kakao/map/presentation/MapViewModel.kt | 26 +++++-- .../map/presentation/MapViewModelFactory.kt | 18 ----- .../kakao/map/presentation/PlaceActivity.kt | 50 ++++++------- .../kakao/map/presentation/PlaceAdapter.kt | 2 +- .../kakao/map/presentation/PlaceViewModel.kt | 37 ++++++--- .../map/presentation/PlaceViewModelFactory.kt | 24 ------ .../tech/kakao/map/utils/ApiKeyProvider.kt | 1 - app/src/main/res/layout/activity_map.xml | 4 +- app/src/main/res/layout/place_item.xml | 3 +- 52 files changed, 522 insertions(+), 356 deletions(-) create mode 100644 app/src/main/java/campus/tech/kakao/map/MyApplication.kt delete mode 100644 app/src/main/java/campus/tech/kakao/map/data/PreferenceHelper.kt create mode 100644 app/src/main/java/campus/tech/kakao/map/data/local/db/AppDatabase.kt create mode 100644 app/src/main/java/campus/tech/kakao/map/data/local/db/SearchQueryDao.kt create mode 100644 app/src/main/java/campus/tech/kakao/map/data/local/db/VisitedPlaceDao.kt create mode 100644 app/src/main/java/campus/tech/kakao/map/data/local/entity/SearchQueryEntity.kt create mode 100644 app/src/main/java/campus/tech/kakao/map/data/local/entity/VisitedPlaceEntity.kt rename app/src/main/java/campus/tech/kakao/map/data/{model => remote/entity}/DocumentEntity.kt (87%) rename app/src/main/java/campus/tech/kakao/map/data/{model => remote/entity}/MetaEntity.kt (83%) rename app/src/main/java/campus/tech/kakao/map/data/{model => remote/entity}/SearchResponse.kt (65%) rename app/src/main/java/campus/tech/kakao/map/data/{ => remote}/network/HttpService.kt (51%) rename app/src/main/java/campus/tech/kakao/map/data/{ => remote}/network/RetrofitObject.kt (67%) rename app/src/main/java/campus/tech/kakao/map/data/{ => remote}/network/RetrofitService.kt (78%) delete mode 100644 app/src/main/java/campus/tech/kakao/map/data/repository/PlaceRepositoryImpl.kt create mode 100644 app/src/main/java/campus/tech/kakao/map/data/repositoryImpl/PlaceRepositoryImpl.kt delete mode 100644 app/src/main/java/campus/tech/kakao/map/data/usecase/GetLastPlaceUseCaseImpl.kt delete mode 100644 app/src/main/java/campus/tech/kakao/map/data/usecase/GetSearchHistoryUseCaseImpl.kt delete mode 100644 app/src/main/java/campus/tech/kakao/map/data/usecase/GetSearchPlacesUseCaseImpl.kt delete mode 100644 app/src/main/java/campus/tech/kakao/map/data/usecase/RemoveSearchQueryUseCaseImpl.kt delete mode 100644 app/src/main/java/campus/tech/kakao/map/data/usecase/SaveLastPlaceUseCaseImpl.kt delete mode 100644 app/src/main/java/campus/tech/kakao/map/data/usecase/SaveSearchQueryUseCaseImpl.kt create mode 100644 app/src/main/java/campus/tech/kakao/map/di/CoroutineDispatcherModule.kt create mode 100644 app/src/main/java/campus/tech/kakao/map/di/DatabaseModule.kt create mode 100644 app/src/main/java/campus/tech/kakao/map/di/NetworkModule.kt create mode 100644 app/src/main/java/campus/tech/kakao/map/di/RepositoryModule.kt create mode 100644 app/src/main/java/campus/tech/kakao/map/di/UsecaseModule.kt rename app/src/main/java/campus/tech/kakao/map/domain/{model => dto}/PlaceVO.kt (82%) create mode 100644 app/src/main/java/campus/tech/kakao/map/domain/usecaseImpl/GetLastPlaceUseCaseImpl.kt create mode 100644 app/src/main/java/campus/tech/kakao/map/domain/usecaseImpl/GetSearchHistoryUseCaseImpl.kt create mode 100644 app/src/main/java/campus/tech/kakao/map/domain/usecaseImpl/GetSearchPlacesUseCaseImpl.kt create mode 100644 app/src/main/java/campus/tech/kakao/map/domain/usecaseImpl/RemoveSearchQueryUseCaseImpl.kt create mode 100644 app/src/main/java/campus/tech/kakao/map/domain/usecaseImpl/SaveLastPlaceUseCaseImpl.kt create mode 100644 app/src/main/java/campus/tech/kakao/map/domain/usecaseImpl/SaveSearchQueryUseCaseImpl.kt delete mode 100644 app/src/main/java/campus/tech/kakao/map/presentation/MapViewModelFactory.kt delete mode 100644 app/src/main/java/campus/tech/kakao/map/presentation/PlaceViewModelFactory.kt diff --git a/app/src/androidTest/java/campus/tech/kakao/map/MapActivityTest.kt b/app/src/androidTest/java/campus/tech/kakao/map/MapActivityTest.kt index d66805c4..9d66f778 100644 --- a/app/src/androidTest/java/campus/tech/kakao/map/MapActivityTest.kt +++ b/app/src/androidTest/java/campus/tech/kakao/map/MapActivityTest.kt @@ -14,7 +14,7 @@ import androidx.test.espresso.matcher.ViewMatchers.withHint import androidx.test.espresso.matcher.ViewMatchers.withId import androidx.test.espresso.matcher.ViewMatchers.withText import androidx.test.ext.junit.rules.ActivityScenarioRule -import campus.tech.kakao.map.domain.model.PlaceVO +import campus.tech.kakao.map.domain.dto.PlaceVO import campus.tech.kakao.map.presentation.MapActivity import campus.tech.kakao.map.presentation.PlaceActivity import org.hamcrest.CoreMatchers.not diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 8c86c630..875989b6 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -2,7 +2,10 @@ + + { - val prefs = context.getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE) - val jsonSearchHistory = prefs.getString(PREF_KEY_SEARCH_QUERY, null) - - return if (jsonSearchHistory != null) { - val type = object : TypeToken>() {}.type - Gson().fromJson(jsonSearchHistory, type) - } else { - emptyList() - } - } - - fun removeSearchQuery(context: Context, query: String) { - val searchHistory = getSearchHistory(context).toMutableList() - searchHistory.remove(query) - val jsonSearchHistory = Gson().toJson(searchHistory) - defaultPrefs(context).edit().putString(PREF_KEY_SEARCH_QUERY, jsonSearchHistory).apply() - } - - fun saveSearchQuery(context: Context, query: String) { - val searchHistory = getSearchHistory(context).toMutableList() - searchHistory.remove(query) - searchHistory.add(0, query) - val jsonSearchHistory = Gson().toJson(searchHistory) - - defaultPrefs(context).edit().putString(PREF_KEY_SEARCH_QUERY, jsonSearchHistory).apply() - } - - fun saveLastPlace(context: Context, place: PlaceVO) { - val jsonLastPlace = Gson().toJson(place) - defaultPrefs(context).edit().putString(PREF_KEY_LAST_PLACE, jsonLastPlace).apply() - } - - fun getLastPlace(context: Context): PlaceVO? { - val prefs = context.getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE) - val jsonLastPlace = prefs.getString(PREF_KEY_LAST_PLACE, null) - - return if (jsonLastPlace != null) { - Gson().fromJson(jsonLastPlace, PlaceVO::class.java) - } else { - null - } - } -} \ No newline at end of file diff --git a/app/src/main/java/campus/tech/kakao/map/data/local/db/AppDatabase.kt b/app/src/main/java/campus/tech/kakao/map/data/local/db/AppDatabase.kt new file mode 100644 index 00000000..7ab4eee8 --- /dev/null +++ b/app/src/main/java/campus/tech/kakao/map/data/local/db/AppDatabase.kt @@ -0,0 +1,12 @@ +package campus.tech.kakao.map.data.local.db + +import androidx.room.Database +import androidx.room.RoomDatabase +import campus.tech.kakao.map.data.local.entity.SearchQueryEntity +import campus.tech.kakao.map.data.local.entity.VisitedPlaceEntity + +@Database(entities = [SearchQueryEntity::class, VisitedPlaceEntity::class], version = 1) +abstract class AppDatabase : RoomDatabase() { + abstract fun searchQueryDao(): SearchQueryDao + abstract fun visitedPlaceDao(): VisitedPlaceDao +} \ No newline at end of file diff --git a/app/src/main/java/campus/tech/kakao/map/data/local/db/SearchQueryDao.kt b/app/src/main/java/campus/tech/kakao/map/data/local/db/SearchQueryDao.kt new file mode 100644 index 00000000..49e81e44 --- /dev/null +++ b/app/src/main/java/campus/tech/kakao/map/data/local/db/SearchQueryDao.kt @@ -0,0 +1,21 @@ +package campus.tech.kakao.map.data.local.db + +import androidx.room.Dao +import androidx.room.Delete +import androidx.room.Insert +import androidx.room.OnConflictStrategy +import androidx.room.Query +import campus.tech.kakao.map.data.local.entity.SearchQueryEntity + +@Dao +interface SearchQueryDao { + + @Query("SELECT * FROM search_queries") + fun getAll(): List + + @Delete + fun delete(searchQueryEntity: SearchQueryEntity) + + @Insert(onConflict = OnConflictStrategy.REPLACE) + fun insert(searchQueryEntity: SearchQueryEntity) +} \ No newline at end of file diff --git a/app/src/main/java/campus/tech/kakao/map/data/local/db/VisitedPlaceDao.kt b/app/src/main/java/campus/tech/kakao/map/data/local/db/VisitedPlaceDao.kt new file mode 100644 index 00000000..28c865f2 --- /dev/null +++ b/app/src/main/java/campus/tech/kakao/map/data/local/db/VisitedPlaceDao.kt @@ -0,0 +1,15 @@ +package campus.tech.kakao.map.data.local.db + +import androidx.room.Dao +import androidx.room.Insert +import androidx.room.Query +import campus.tech.kakao.map.data.local.entity.VisitedPlaceEntity + +@Dao +interface VisitedPlaceDao { + @Query("SELECT * FROM visited_places ORDER BY id DESC LIMIT 1") + fun getLastPlace(): VisitedPlaceEntity? + + @Insert + fun insert(place: VisitedPlaceEntity) +} \ No newline at end of file diff --git a/app/src/main/java/campus/tech/kakao/map/data/local/entity/SearchQueryEntity.kt b/app/src/main/java/campus/tech/kakao/map/data/local/entity/SearchQueryEntity.kt new file mode 100644 index 00000000..be06ead5 --- /dev/null +++ b/app/src/main/java/campus/tech/kakao/map/data/local/entity/SearchQueryEntity.kt @@ -0,0 +1,9 @@ +package campus.tech.kakao.map.data.local.entity + +import androidx.room.Entity +import androidx.room.PrimaryKey + +@Entity(tableName = "search_queries") +data class SearchQueryEntity( + @PrimaryKey val query: String +) diff --git a/app/src/main/java/campus/tech/kakao/map/data/local/entity/VisitedPlaceEntity.kt b/app/src/main/java/campus/tech/kakao/map/data/local/entity/VisitedPlaceEntity.kt new file mode 100644 index 00000000..992fb536 --- /dev/null +++ b/app/src/main/java/campus/tech/kakao/map/data/local/entity/VisitedPlaceEntity.kt @@ -0,0 +1,14 @@ +package campus.tech.kakao.map.data.local.entity + +import androidx.room.Entity +import androidx.room.PrimaryKey + +@Entity(tableName = "visited_places") +data class VisitedPlaceEntity( + @PrimaryKey(autoGenerate = true) val id: Int = 0, + val placeName: String, + val addressName: String, + val categoryName: String, + val latitude: Double, + val longitude: Double, +) diff --git a/app/src/main/java/campus/tech/kakao/map/data/model/DocumentEntity.kt b/app/src/main/java/campus/tech/kakao/map/data/remote/entity/DocumentEntity.kt similarity index 87% rename from app/src/main/java/campus/tech/kakao/map/data/model/DocumentEntity.kt rename to app/src/main/java/campus/tech/kakao/map/data/remote/entity/DocumentEntity.kt index 49b2281a..7b23f2aa 100644 --- a/app/src/main/java/campus/tech/kakao/map/data/model/DocumentEntity.kt +++ b/app/src/main/java/campus/tech/kakao/map/data/remote/entity/DocumentEntity.kt @@ -1,8 +1,11 @@ -package campus.tech.kakao.map.data.model +package campus.tech.kakao.map.data.remote.entity +import androidx.room.PrimaryKey import com.google.gson.annotations.SerializedName + data class DocumentEntity( + @PrimaryKey val id: String, @SerializedName("place_name") val placeName: String, diff --git a/app/src/main/java/campus/tech/kakao/map/data/model/MetaEntity.kt b/app/src/main/java/campus/tech/kakao/map/data/remote/entity/MetaEntity.kt similarity index 83% rename from app/src/main/java/campus/tech/kakao/map/data/model/MetaEntity.kt rename to app/src/main/java/campus/tech/kakao/map/data/remote/entity/MetaEntity.kt index f9a955a0..50de8d5d 100644 --- a/app/src/main/java/campus/tech/kakao/map/data/model/MetaEntity.kt +++ b/app/src/main/java/campus/tech/kakao/map/data/remote/entity/MetaEntity.kt @@ -1,4 +1,4 @@ -package campus.tech.kakao.map.data.model +package campus.tech.kakao.map.data.remote.entity import com.google.gson.annotations.SerializedName diff --git a/app/src/main/java/campus/tech/kakao/map/data/model/SearchResponse.kt b/app/src/main/java/campus/tech/kakao/map/data/remote/entity/SearchResponse.kt similarity index 65% rename from app/src/main/java/campus/tech/kakao/map/data/model/SearchResponse.kt rename to app/src/main/java/campus/tech/kakao/map/data/remote/entity/SearchResponse.kt index ba47b538..9da32c3e 100644 --- a/app/src/main/java/campus/tech/kakao/map/data/model/SearchResponse.kt +++ b/app/src/main/java/campus/tech/kakao/map/data/remote/entity/SearchResponse.kt @@ -1,4 +1,4 @@ -package campus.tech.kakao.map.data.model +package campus.tech.kakao.map.data.remote.entity data class SearchResponse( val meta: MetaEntity, diff --git a/app/src/main/java/campus/tech/kakao/map/data/network/HttpService.kt b/app/src/main/java/campus/tech/kakao/map/data/remote/network/HttpService.kt similarity index 51% rename from app/src/main/java/campus/tech/kakao/map/data/network/HttpService.kt rename to app/src/main/java/campus/tech/kakao/map/data/remote/network/HttpService.kt index 58bee3fd..1e7f4198 100644 --- a/app/src/main/java/campus/tech/kakao/map/data/network/HttpService.kt +++ b/app/src/main/java/campus/tech/kakao/map/data/remote/network/HttpService.kt @@ -1,37 +1,39 @@ -package campus.tech.kakao.map.data.network +package campus.tech.kakao.map.data.remote.network import android.util.Log -import campus.tech.kakao.map.data.model.SearchResponse +import campus.tech.kakao.map.data.remote.entity.SearchResponse import campus.tech.kakao.map.utils.ApiKeyProvider import com.google.gson.Gson +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.withContext import java.net.HttpURLConnection import java.net.URL +import javax.inject.Inject -object HttpService { - private const val BASE_URL = "https://dapi.kakao.com/" +class HttpService @Inject constructor( + private val apiKeyProvider: ApiKeyProvider, + private val baseUrl: String +) { - fun searchKeyword(query: String, callback: (SearchResponse?) -> Unit) { - Thread { - val url = "${BASE_URL}v2/local/search/keyword.json?query=$query" + suspend fun searchKeyword(query: String): SearchResponse? = withContext(Dispatchers.IO) { + val url = "${baseUrl}v2/local/search/keyword.json?query=$query" val connection = URL(url).openConnection() as HttpURLConnection try { connection.requestMethod = "GET" - connection.setRequestProperty("Authorization", ApiKeyProvider.KAKAO_REST_API_KEY) + connection.setRequestProperty("Authorization", apiKeyProvider.KAKAO_REST_API_KEY) val responseCode = connection.responseCode if (responseCode == HttpURLConnection.HTTP_OK) { val response = connection.inputStream.bufferedReader().readText() - callback(Gson().fromJson(response, SearchResponse::class.java)) + Gson().fromJson(response, SearchResponse::class.java) } else { Log.d( "testt", - "Response failed: ${connection.errorStream.bufferedReader().readText()}" - ) - callback(null) + "Response failed: ${connection.errorStream.bufferedReader().readText()}") + null + null } } finally { connection.disconnect() } - }.start() + } } - -} \ No newline at end of file diff --git a/app/src/main/java/campus/tech/kakao/map/data/network/RetrofitObject.kt b/app/src/main/java/campus/tech/kakao/map/data/remote/network/RetrofitObject.kt similarity index 67% rename from app/src/main/java/campus/tech/kakao/map/data/network/RetrofitObject.kt rename to app/src/main/java/campus/tech/kakao/map/data/remote/network/RetrofitObject.kt index 60d06bec..daa91449 100644 --- a/app/src/main/java/campus/tech/kakao/map/data/network/RetrofitObject.kt +++ b/app/src/main/java/campus/tech/kakao/map/data/remote/network/RetrofitObject.kt @@ -1,9 +1,5 @@ -package campus.tech.kakao.map.data.network +package campus.tech.kakao.map.data.remote.network -import campus.tech.kakao.map.data.model.SearchResponse -import retrofit2.Call -import retrofit2.Callback -import retrofit2.Response import retrofit2.Retrofit import retrofit2.converter.gson.GsonConverterFactory diff --git a/app/src/main/java/campus/tech/kakao/map/data/network/RetrofitService.kt b/app/src/main/java/campus/tech/kakao/map/data/remote/network/RetrofitService.kt similarity index 78% rename from app/src/main/java/campus/tech/kakao/map/data/network/RetrofitService.kt rename to app/src/main/java/campus/tech/kakao/map/data/remote/network/RetrofitService.kt index 5958b68a..14aab2aa 100644 --- a/app/src/main/java/campus/tech/kakao/map/data/network/RetrofitService.kt +++ b/app/src/main/java/campus/tech/kakao/map/data/remote/network/RetrofitService.kt @@ -1,6 +1,6 @@ -package campus.tech.kakao.map.data.network +package campus.tech.kakao.map.data.remote.network -import campus.tech.kakao.map.data.model.SearchResponse +import campus.tech.kakao.map.data.remote.entity.SearchResponse import campus.tech.kakao.map.utils.ApiKeyProvider import retrofit2.Call import retrofit2.http.GET diff --git a/app/src/main/java/campus/tech/kakao/map/data/repository/PlaceRepositoryImpl.kt b/app/src/main/java/campus/tech/kakao/map/data/repository/PlaceRepositoryImpl.kt deleted file mode 100644 index c6feb5f3..00000000 --- a/app/src/main/java/campus/tech/kakao/map/data/repository/PlaceRepositoryImpl.kt +++ /dev/null @@ -1,61 +0,0 @@ -package campus.tech.kakao.map.data.repository - -import android.content.Context -import android.util.Log -import campus.tech.kakao.map.data.PreferenceHelper -import campus.tech.kakao.map.data.model.SearchResponse -import campus.tech.kakao.map.data.network.HttpService -import campus.tech.kakao.map.data.network.RetrofitObject -import campus.tech.kakao.map.domain.model.PlaceVO -import campus.tech.kakao.map.domain.repository.PlaceRepository -import retrofit2.Call -import retrofit2.Callback -import retrofit2.Response - -class PlaceRepositoryImpl(private val context: Context) : PlaceRepository { -// private val retrofitService = RetrofitObject.retrofitService - override fun searchPlaces(query: String, callback: (List?) -> Unit) { - HttpService.searchKeyword(query = query){ response -> -// override fun onResponse( -// call: Call, -// response: Response -// ) { - if (response != null) { - val places = response?.documents?.map { - PlaceVO( - placeName = it.placeName, - addressName = it.addressName, - categoryName = it.categoryGroupName, - latitude = it.y.toDouble(), - longitude = it.x.toDouble() - ) - } - callback(places) - } else { - Log.d("testt", "Response failed: ${response.toString()}") - callback(null) - } - } - } - - - override fun saveSearchQuery(place: PlaceVO) { - PreferenceHelper.saveSearchQuery(context, place.placeName) - } - - override fun getSearchHistory(): List { - return PreferenceHelper.getSearchHistory(context) - } - - override fun removeSearchQuery(query: String) { - PreferenceHelper.removeSearchQuery(context, query) - } - - override fun saveLastPlace(place: PlaceVO) { - PreferenceHelper.saveLastPlace(context, place) - } - - override fun getLastPlace(): PlaceVO? { - return PreferenceHelper.getLastPlace(context) - } -} \ No newline at end of file diff --git a/app/src/main/java/campus/tech/kakao/map/data/repositoryImpl/PlaceRepositoryImpl.kt b/app/src/main/java/campus/tech/kakao/map/data/repositoryImpl/PlaceRepositoryImpl.kt new file mode 100644 index 00000000..4e76621a --- /dev/null +++ b/app/src/main/java/campus/tech/kakao/map/data/repositoryImpl/PlaceRepositoryImpl.kt @@ -0,0 +1,75 @@ +package campus.tech.kakao.map.data.repositoryImpl + +import campus.tech.kakao.map.data.local.db.SearchQueryDao +import campus.tech.kakao.map.data.local.db.VisitedPlaceDao +import campus.tech.kakao.map.data.local.entity.SearchQueryEntity +import campus.tech.kakao.map.data.local.entity.VisitedPlaceEntity +import campus.tech.kakao.map.data.remote.network.HttpService +import campus.tech.kakao.map.domain.dto.PlaceVO +import campus.tech.kakao.map.domain.repository.PlaceRepository +import kotlinx.coroutines.CoroutineDispatcher +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.withContext +import javax.inject.Inject +import javax.inject.Singleton + +@Singleton +class PlaceRepositoryImpl @Inject constructor( + private val searchQueryDao: SearchQueryDao, + private val visitedPlaceDao: VisitedPlaceDao, + private val httpService: HttpService, + private val ioDispatcher: CoroutineDispatcher +) : PlaceRepository { + override suspend fun searchPlaces(query: String): List? = withContext(Dispatchers.IO) { + + val response = httpService.searchKeyword(query = query) + response?.documents?.map { + PlaceVO( + placeName = it.placeName, + addressName = it.addressName, + categoryName = it.categoryGroupName, + latitude = it.y.toDouble(), + longitude = it.x.toDouble() + ) + } + } + + + override suspend fun saveSearchQuery(place: PlaceVO): Unit = withContext(ioDispatcher) { + val queryEntity = SearchQueryEntity(query = place.placeName) + searchQueryDao.insert(queryEntity) + } + + override suspend fun getSearchHistory(): List = withContext(ioDispatcher) { + searchQueryDao.getAll().map { it.query }.reversed() + } + + override suspend fun removeSearchQuery(query: String) = withContext(ioDispatcher) { + val queryEntity = SearchQueryEntity(query = query) + searchQueryDao.delete(queryEntity) + } + + override suspend fun saveLastPlace(place: PlaceVO) = withContext(ioDispatcher) { + val visitedPlaceEntity = VisitedPlaceEntity( + placeName = place.placeName, + addressName = place.addressName, + categoryName = place.categoryName, + latitude = place.latitude, + longitude = place.longitude + ) + visitedPlaceDao.insert(visitedPlaceEntity) + } + + override suspend fun getLastPlace(): PlaceVO? = withContext(ioDispatcher) { + val lastPlace = visitedPlaceDao.getLastPlace() + lastPlace?.let { + PlaceVO( + placeName = it.placeName, + addressName = it.addressName, + categoryName = it.categoryName, + latitude = it.latitude, + longitude = it.longitude + ) + } + } +} \ No newline at end of file diff --git a/app/src/main/java/campus/tech/kakao/map/data/usecase/GetLastPlaceUseCaseImpl.kt b/app/src/main/java/campus/tech/kakao/map/data/usecase/GetLastPlaceUseCaseImpl.kt deleted file mode 100644 index f7b0ad1b..00000000 --- a/app/src/main/java/campus/tech/kakao/map/data/usecase/GetLastPlaceUseCaseImpl.kt +++ /dev/null @@ -1,13 +0,0 @@ -package campus.tech.kakao.map.data.usecase - -import android.util.Log -import campus.tech.kakao.map.domain.model.PlaceVO -import campus.tech.kakao.map.domain.repository.PlaceRepository -import campus.tech.kakao.map.domain.usecase.GetLastPlaceUseCase - -class GetLastPlaceUseCaseImpl (private val placeRepository: PlaceRepository): GetLastPlaceUseCase { - override fun invoke(): PlaceVO? { - return placeRepository.getLastPlace() - } - -} \ No newline at end of file diff --git a/app/src/main/java/campus/tech/kakao/map/data/usecase/GetSearchHistoryUseCaseImpl.kt b/app/src/main/java/campus/tech/kakao/map/data/usecase/GetSearchHistoryUseCaseImpl.kt deleted file mode 100644 index 326ab8a0..00000000 --- a/app/src/main/java/campus/tech/kakao/map/data/usecase/GetSearchHistoryUseCaseImpl.kt +++ /dev/null @@ -1,12 +0,0 @@ -package campus.tech.kakao.map.data.usecase - -import campus.tech.kakao.map.domain.repository.PlaceRepository -import campus.tech.kakao.map.domain.usecase.GetSearchHistoryUseCase -import campus.tech.kakao.map.domain.usecase.GetSearchPlacesUseCase - -class GetSearchHistoryUseCaseImpl(private val placeRepository: PlaceRepository) : - GetSearchHistoryUseCase { - override fun invoke(): List { - return placeRepository.getSearchHistory() - } -} \ No newline at end of file diff --git a/app/src/main/java/campus/tech/kakao/map/data/usecase/GetSearchPlacesUseCaseImpl.kt b/app/src/main/java/campus/tech/kakao/map/data/usecase/GetSearchPlacesUseCaseImpl.kt deleted file mode 100644 index a6eb943f..00000000 --- a/app/src/main/java/campus/tech/kakao/map/data/usecase/GetSearchPlacesUseCaseImpl.kt +++ /dev/null @@ -1,13 +0,0 @@ -package campus.tech.kakao.map.data.usecase - -import campus.tech.kakao.map.domain.model.PlaceVO -import campus.tech.kakao.map.domain.repository.PlaceRepository -import campus.tech.kakao.map.domain.usecase.GetSearchPlacesUseCase - -class GetSearchPlacesUseCaseImpl(private val placeRepository: PlaceRepository) : - GetSearchPlacesUseCase { - override fun invoke(query: String, callback: (List?) -> Unit) { - placeRepository.searchPlaces(query, callback) - } - -} diff --git a/app/src/main/java/campus/tech/kakao/map/data/usecase/RemoveSearchQueryUseCaseImpl.kt b/app/src/main/java/campus/tech/kakao/map/data/usecase/RemoveSearchQueryUseCaseImpl.kt deleted file mode 100644 index d607b3a6..00000000 --- a/app/src/main/java/campus/tech/kakao/map/data/usecase/RemoveSearchQueryUseCaseImpl.kt +++ /dev/null @@ -1,13 +0,0 @@ -package campus.tech.kakao.map.data.usecase - -import campus.tech.kakao.map.domain.repository.PlaceRepository -import campus.tech.kakao.map.domain.usecase.GetSearchPlacesUseCase -import campus.tech.kakao.map.domain.usecase.RemoveSearchQueryUseCase - -class RemoveSearchQueryUseCaseImpl(private val placeRepository: PlaceRepository) : - RemoveSearchQueryUseCase { - override fun invoke(query: String) { - placeRepository.removeSearchQuery(query) - } - -} \ No newline at end of file diff --git a/app/src/main/java/campus/tech/kakao/map/data/usecase/SaveLastPlaceUseCaseImpl.kt b/app/src/main/java/campus/tech/kakao/map/data/usecase/SaveLastPlaceUseCaseImpl.kt deleted file mode 100644 index 4303af4b..00000000 --- a/app/src/main/java/campus/tech/kakao/map/data/usecase/SaveLastPlaceUseCaseImpl.kt +++ /dev/null @@ -1,13 +0,0 @@ -package campus.tech.kakao.map.data.usecase - -import campus.tech.kakao.map.domain.model.PlaceVO -import campus.tech.kakao.map.domain.repository.PlaceRepository -import campus.tech.kakao.map.domain.usecase.GetLastPlaceUseCase -import campus.tech.kakao.map.domain.usecase.SaveLastPlaceUseCase - -class SaveLastPlaceUseCaseImpl(private val placeRepository: PlaceRepository): SaveLastPlaceUseCase { - override fun invoke(place: PlaceVO) { - placeRepository.saveLastPlace(place) - } - -} \ No newline at end of file diff --git a/app/src/main/java/campus/tech/kakao/map/data/usecase/SaveSearchQueryUseCaseImpl.kt b/app/src/main/java/campus/tech/kakao/map/data/usecase/SaveSearchQueryUseCaseImpl.kt deleted file mode 100644 index b3da6e26..00000000 --- a/app/src/main/java/campus/tech/kakao/map/data/usecase/SaveSearchQueryUseCaseImpl.kt +++ /dev/null @@ -1,13 +0,0 @@ -package campus.tech.kakao.map.data.usecase - -import campus.tech.kakao.map.domain.model.PlaceVO -import campus.tech.kakao.map.domain.repository.PlaceRepository -import campus.tech.kakao.map.domain.usecase.SaveSearchQueryUseCase - -class SaveSearchQueryUseCaseImpl(private val placeRepository: PlaceRepository) : - SaveSearchQueryUseCase { - override fun invoke(place: PlaceVO) { - placeRepository.saveSearchQuery(place) - } - -} \ No newline at end of file diff --git a/app/src/main/java/campus/tech/kakao/map/di/CoroutineDispatcherModule.kt b/app/src/main/java/campus/tech/kakao/map/di/CoroutineDispatcherModule.kt new file mode 100644 index 00000000..8b107390 --- /dev/null +++ b/app/src/main/java/campus/tech/kakao/map/di/CoroutineDispatcherModule.kt @@ -0,0 +1,18 @@ +package campus.tech.kakao.map.di + +import dagger.Module +import dagger.Provides +import dagger.hilt.InstallIn +import dagger.hilt.components.SingletonComponent +import kotlinx.coroutines.CoroutineDispatcher +import kotlinx.coroutines.Dispatchers +import javax.inject.Singleton + +@InstallIn(SingletonComponent::class) +@Module +object CoroutineDispatcherModule { + + @Provides + @Singleton + fun provideIODispatcher(): CoroutineDispatcher = Dispatchers.IO +} \ No newline at end of file diff --git a/app/src/main/java/campus/tech/kakao/map/di/DatabaseModule.kt b/app/src/main/java/campus/tech/kakao/map/di/DatabaseModule.kt new file mode 100644 index 00000000..ebb428b5 --- /dev/null +++ b/app/src/main/java/campus/tech/kakao/map/di/DatabaseModule.kt @@ -0,0 +1,41 @@ +package campus.tech.kakao.map.di + +import android.content.Context +import androidx.room.Room +import campus.tech.kakao.map.data.local.db.AppDatabase +import dagger.Module +import dagger.Provides +import dagger.hilt.InstallIn +import dagger.hilt.android.qualifiers.ApplicationContext +import dagger.hilt.components.SingletonComponent +import javax.inject.Qualifier +import javax.inject.Singleton + +@Qualifier +@Retention(AnnotationRetention.BINARY) +annotation class DatabaseName + +@InstallIn(SingletonComponent::class) +@Module +object DatabaseModule { + + @Provides + @DatabaseName + fun provideDatabaseName(): String = "kakao_map" + + @Provides + @Singleton + fun provideDatabase(@ApplicationContext appContext: Context, @DatabaseName dbName: String): AppDatabase { + return Room.databaseBuilder( + appContext, + AppDatabase::class.java, + dbName + ).build() + } + + @Provides + fun provideSearchQueryDao(database: AppDatabase) = database.searchQueryDao() + + @Provides + fun provideVisitedPlaceDao(database: AppDatabase) = database.visitedPlaceDao() +} \ No newline at end of file diff --git a/app/src/main/java/campus/tech/kakao/map/di/NetworkModule.kt b/app/src/main/java/campus/tech/kakao/map/di/NetworkModule.kt new file mode 100644 index 00000000..f8838067 --- /dev/null +++ b/app/src/main/java/campus/tech/kakao/map/di/NetworkModule.kt @@ -0,0 +1,34 @@ +package campus.tech.kakao.map.di + +import campus.tech.kakao.map.data.remote.network.HttpService +import campus.tech.kakao.map.utils.ApiKeyProvider +import dagger.Module +import dagger.Provides +import dagger.hilt.InstallIn +import dagger.hilt.components.SingletonComponent +import javax.inject.Singleton + +@InstallIn(SingletonComponent::class) +@Module +object NetworkModule { + // 데이터베이스와 네트워크 모듈은 전역적으로 사용할 인스턴스 object 로 사용 + // Usecase와 Repo는 구현체와 인터페이스를 바인딩하기 위해 abstract class로 사용 + @Provides + @Singleton + fun provideBaseUrl(): String { + return "https://dapi.kakao.com/" + } + + @Provides + @Singleton + fun provideApiKeyProvider(): ApiKeyProvider = ApiKeyProvider + + @Provides + @Singleton + fun provideHttpService( + apiKeyProvider: ApiKeyProvider, + baseUrl: String + ): HttpService { + return HttpService(apiKeyProvider, baseUrl) + } +} \ No newline at end of file diff --git a/app/src/main/java/campus/tech/kakao/map/di/RepositoryModule.kt b/app/src/main/java/campus/tech/kakao/map/di/RepositoryModule.kt new file mode 100644 index 00000000..8f0e32bb --- /dev/null +++ b/app/src/main/java/campus/tech/kakao/map/di/RepositoryModule.kt @@ -0,0 +1,19 @@ +package campus.tech.kakao.map.di + +import campus.tech.kakao.map.data.repositoryImpl.PlaceRepositoryImpl +import campus.tech.kakao.map.domain.repository.PlaceRepository +import dagger.Binds +import dagger.Module +import dagger.hilt.InstallIn +import dagger.hilt.components.SingletonComponent +import javax.inject.Singleton + +@InstallIn(SingletonComponent::class) +@Module +abstract class RepositoryModule { + + @Binds + @Singleton + abstract fun bindRepository(impl: PlaceRepositoryImpl): PlaceRepository + +} diff --git a/app/src/main/java/campus/tech/kakao/map/di/UsecaseModule.kt b/app/src/main/java/campus/tech/kakao/map/di/UsecaseModule.kt new file mode 100644 index 00000000..a759fe1e --- /dev/null +++ b/app/src/main/java/campus/tech/kakao/map/di/UsecaseModule.kt @@ -0,0 +1,54 @@ +package campus.tech.kakao.map.di + +import campus.tech.kakao.map.domain.usecaseImpl.GetLastPlaceUseCaseImpl +import campus.tech.kakao.map.domain.usecaseImpl.GetSearchHistoryUseCaseImpl +import campus.tech.kakao.map.domain.usecaseImpl.GetSearchPlacesUseCaseImpl +import campus.tech.kakao.map.domain.usecaseImpl.RemoveSearchQueryUseCaseImpl +import campus.tech.kakao.map.domain.usecaseImpl.SaveLastPlaceUseCaseImpl +import campus.tech.kakao.map.domain.usecaseImpl.SaveSearchQueryUseCaseImpl +import campus.tech.kakao.map.domain.usecase.GetLastPlaceUseCase +import campus.tech.kakao.map.domain.usecase.GetSearchHistoryUseCase +import campus.tech.kakao.map.domain.usecase.GetSearchPlacesUseCase +import campus.tech.kakao.map.domain.usecase.RemoveSearchQueryUseCase +import campus.tech.kakao.map.domain.usecase.SaveLastPlaceUseCase +import campus.tech.kakao.map.domain.usecase.SaveSearchQueryUseCase +import dagger.Binds +import dagger.Module +import dagger.hilt.InstallIn +import dagger.hilt.components.SingletonComponent + +@InstallIn(SingletonComponent::class) +@Module +abstract class UsecaseModule { + + @Binds + abstract fun bindSaveLastPlaceUseCase( + impl: SaveLastPlaceUseCaseImpl + ): SaveLastPlaceUseCase + + + @Binds + abstract fun bindGetLastPlaceUseCase( + impl: GetLastPlaceUseCaseImpl + ): GetLastPlaceUseCase + + @Binds + abstract fun bindGetSearchPlacesUseCase( + impl: GetSearchPlacesUseCaseImpl + ): GetSearchPlacesUseCase + + @Binds + abstract fun bindSaveSearchQueryUseCase( + impl: SaveSearchQueryUseCaseImpl + ): SaveSearchQueryUseCase + + @Binds + abstract fun bindGetSearchHistoryUseCase( + impl: GetSearchHistoryUseCaseImpl + ): GetSearchHistoryUseCase + + @Binds + abstract fun bindRemoveSearchQueryUseCase( + impl: RemoveSearchQueryUseCaseImpl + ): RemoveSearchQueryUseCase +} diff --git a/app/src/main/java/campus/tech/kakao/map/domain/model/PlaceVO.kt b/app/src/main/java/campus/tech/kakao/map/domain/dto/PlaceVO.kt similarity index 82% rename from app/src/main/java/campus/tech/kakao/map/domain/model/PlaceVO.kt rename to app/src/main/java/campus/tech/kakao/map/domain/dto/PlaceVO.kt index 869d75d6..2fe4fd4a 100644 --- a/app/src/main/java/campus/tech/kakao/map/domain/model/PlaceVO.kt +++ b/app/src/main/java/campus/tech/kakao/map/domain/dto/PlaceVO.kt @@ -1,4 +1,4 @@ -package campus.tech.kakao.map.domain.model +package campus.tech.kakao.map.domain.dto import java.io.Serializable diff --git a/app/src/main/java/campus/tech/kakao/map/domain/repository/PlaceRepository.kt b/app/src/main/java/campus/tech/kakao/map/domain/repository/PlaceRepository.kt index b12a0cb0..69021336 100644 --- a/app/src/main/java/campus/tech/kakao/map/domain/repository/PlaceRepository.kt +++ b/app/src/main/java/campus/tech/kakao/map/domain/repository/PlaceRepository.kt @@ -1,12 +1,12 @@ package campus.tech.kakao.map.domain.repository -import campus.tech.kakao.map.domain.model.PlaceVO +import campus.tech.kakao.map.domain.dto.PlaceVO interface PlaceRepository { - fun searchPlaces(query: String, callback: (List?) -> Unit) - fun saveSearchQuery(place: PlaceVO) - fun getSearchHistory(): List - fun removeSearchQuery(query: String) - fun saveLastPlace(place: PlaceVO) - fun getLastPlace(): PlaceVO? + suspend fun searchPlaces(query: String) : List? + suspend fun saveSearchQuery(place: PlaceVO) + suspend fun getSearchHistory(): List + suspend fun removeSearchQuery(query: String) + suspend fun saveLastPlace(place: PlaceVO) + suspend fun getLastPlace(): PlaceVO? } diff --git a/app/src/main/java/campus/tech/kakao/map/domain/usecase/GetLastPlaceUseCase.kt b/app/src/main/java/campus/tech/kakao/map/domain/usecase/GetLastPlaceUseCase.kt index d4e17670..7b3488d0 100644 --- a/app/src/main/java/campus/tech/kakao/map/domain/usecase/GetLastPlaceUseCase.kt +++ b/app/src/main/java/campus/tech/kakao/map/domain/usecase/GetLastPlaceUseCase.kt @@ -1,7 +1,7 @@ package campus.tech.kakao.map.domain.usecase -import campus.tech.kakao.map.domain.model.PlaceVO +import campus.tech.kakao.map.domain.dto.PlaceVO interface GetLastPlaceUseCase { - operator fun invoke(): PlaceVO? + suspend operator fun invoke(): PlaceVO? } \ No newline at end of file diff --git a/app/src/main/java/campus/tech/kakao/map/domain/usecase/GetSearchHistoryUseCase.kt b/app/src/main/java/campus/tech/kakao/map/domain/usecase/GetSearchHistoryUseCase.kt index c01173c2..c294084f 100644 --- a/app/src/main/java/campus/tech/kakao/map/domain/usecase/GetSearchHistoryUseCase.kt +++ b/app/src/main/java/campus/tech/kakao/map/domain/usecase/GetSearchHistoryUseCase.kt @@ -1,5 +1,5 @@ package campus.tech.kakao.map.domain.usecase interface GetSearchHistoryUseCase { - operator fun invoke(): List + suspend operator fun invoke(): List } \ No newline at end of file diff --git a/app/src/main/java/campus/tech/kakao/map/domain/usecase/GetSearchPlacesUseCase.kt b/app/src/main/java/campus/tech/kakao/map/domain/usecase/GetSearchPlacesUseCase.kt index 8c0f499c..cc799867 100644 --- a/app/src/main/java/campus/tech/kakao/map/domain/usecase/GetSearchPlacesUseCase.kt +++ b/app/src/main/java/campus/tech/kakao/map/domain/usecase/GetSearchPlacesUseCase.kt @@ -1,7 +1,7 @@ package campus.tech.kakao.map.domain.usecase -import campus.tech.kakao.map.domain.model.PlaceVO +import campus.tech.kakao.map.domain.dto.PlaceVO interface GetSearchPlacesUseCase { - operator fun invoke(query: String, callback: (List?) -> Unit) + suspend operator fun invoke(query: String): List? } \ No newline at end of file diff --git a/app/src/main/java/campus/tech/kakao/map/domain/usecase/RemoveSearchQueryUseCase.kt b/app/src/main/java/campus/tech/kakao/map/domain/usecase/RemoveSearchQueryUseCase.kt index 5b56be53..c05d0a3d 100644 --- a/app/src/main/java/campus/tech/kakao/map/domain/usecase/RemoveSearchQueryUseCase.kt +++ b/app/src/main/java/campus/tech/kakao/map/domain/usecase/RemoveSearchQueryUseCase.kt @@ -1,5 +1,5 @@ package campus.tech.kakao.map.domain.usecase interface RemoveSearchQueryUseCase { - operator fun invoke(query: String) + suspend operator fun invoke(query: String) } \ No newline at end of file diff --git a/app/src/main/java/campus/tech/kakao/map/domain/usecase/SaveLastPlaceUseCase.kt b/app/src/main/java/campus/tech/kakao/map/domain/usecase/SaveLastPlaceUseCase.kt index 3083604d..18a79f71 100644 --- a/app/src/main/java/campus/tech/kakao/map/domain/usecase/SaveLastPlaceUseCase.kt +++ b/app/src/main/java/campus/tech/kakao/map/domain/usecase/SaveLastPlaceUseCase.kt @@ -1,7 +1,7 @@ package campus.tech.kakao.map.domain.usecase -import campus.tech.kakao.map.domain.model.PlaceVO +import campus.tech.kakao.map.domain.dto.PlaceVO interface SaveLastPlaceUseCase { - operator fun invoke(place: PlaceVO) + suspend operator fun invoke(place: PlaceVO) } \ No newline at end of file diff --git a/app/src/main/java/campus/tech/kakao/map/domain/usecase/SaveSearchQueryUseCase.kt b/app/src/main/java/campus/tech/kakao/map/domain/usecase/SaveSearchQueryUseCase.kt index 5991356c..067dd1b6 100644 --- a/app/src/main/java/campus/tech/kakao/map/domain/usecase/SaveSearchQueryUseCase.kt +++ b/app/src/main/java/campus/tech/kakao/map/domain/usecase/SaveSearchQueryUseCase.kt @@ -1,7 +1,7 @@ package campus.tech.kakao.map.domain.usecase -import campus.tech.kakao.map.domain.model.PlaceVO +import campus.tech.kakao.map.domain.dto.PlaceVO interface SaveSearchQueryUseCase { - operator fun invoke(place: PlaceVO) + suspend operator fun invoke(place: PlaceVO) } \ No newline at end of file diff --git a/app/src/main/java/campus/tech/kakao/map/domain/usecaseImpl/GetLastPlaceUseCaseImpl.kt b/app/src/main/java/campus/tech/kakao/map/domain/usecaseImpl/GetLastPlaceUseCaseImpl.kt new file mode 100644 index 00000000..b134d064 --- /dev/null +++ b/app/src/main/java/campus/tech/kakao/map/domain/usecaseImpl/GetLastPlaceUseCaseImpl.kt @@ -0,0 +1,13 @@ +package campus.tech.kakao.map.domain.usecaseImpl + +import campus.tech.kakao.map.domain.dto.PlaceVO +import campus.tech.kakao.map.domain.repository.PlaceRepository +import campus.tech.kakao.map.domain.usecase.GetLastPlaceUseCase +import javax.inject.Inject + +class GetLastPlaceUseCaseImpl @Inject constructor (private val placeRepository: PlaceRepository): GetLastPlaceUseCase { + override suspend fun invoke(): PlaceVO? { + return placeRepository.getLastPlace() + } + +} \ No newline at end of file diff --git a/app/src/main/java/campus/tech/kakao/map/domain/usecaseImpl/GetSearchHistoryUseCaseImpl.kt b/app/src/main/java/campus/tech/kakao/map/domain/usecaseImpl/GetSearchHistoryUseCaseImpl.kt new file mode 100644 index 00000000..bd3808f0 --- /dev/null +++ b/app/src/main/java/campus/tech/kakao/map/domain/usecaseImpl/GetSearchHistoryUseCaseImpl.kt @@ -0,0 +1,12 @@ +package campus.tech.kakao.map.domain.usecaseImpl + +import campus.tech.kakao.map.domain.repository.PlaceRepository +import campus.tech.kakao.map.domain.usecase.GetSearchHistoryUseCase +import javax.inject.Inject + +class GetSearchHistoryUseCaseImpl @Inject constructor(private val placeRepository: PlaceRepository) : + GetSearchHistoryUseCase { + override suspend fun invoke(): List { + return placeRepository.getSearchHistory() + } +} \ No newline at end of file diff --git a/app/src/main/java/campus/tech/kakao/map/domain/usecaseImpl/GetSearchPlacesUseCaseImpl.kt b/app/src/main/java/campus/tech/kakao/map/domain/usecaseImpl/GetSearchPlacesUseCaseImpl.kt new file mode 100644 index 00000000..a875ec37 --- /dev/null +++ b/app/src/main/java/campus/tech/kakao/map/domain/usecaseImpl/GetSearchPlacesUseCaseImpl.kt @@ -0,0 +1,14 @@ +package campus.tech.kakao.map.domain.usecaseImpl + +import campus.tech.kakao.map.domain.dto.PlaceVO +import campus.tech.kakao.map.domain.repository.PlaceRepository +import campus.tech.kakao.map.domain.usecase.GetSearchPlacesUseCase +import javax.inject.Inject + +class GetSearchPlacesUseCaseImpl @Inject constructor(private val placeRepository: PlaceRepository) : + GetSearchPlacesUseCase { + override suspend fun invoke(query: String): List? { + return placeRepository.searchPlaces(query) + } + +} diff --git a/app/src/main/java/campus/tech/kakao/map/domain/usecaseImpl/RemoveSearchQueryUseCaseImpl.kt b/app/src/main/java/campus/tech/kakao/map/domain/usecaseImpl/RemoveSearchQueryUseCaseImpl.kt new file mode 100644 index 00000000..ed7b741d --- /dev/null +++ b/app/src/main/java/campus/tech/kakao/map/domain/usecaseImpl/RemoveSearchQueryUseCaseImpl.kt @@ -0,0 +1,13 @@ +package campus.tech.kakao.map.domain.usecaseImpl + +import campus.tech.kakao.map.domain.repository.PlaceRepository +import campus.tech.kakao.map.domain.usecase.RemoveSearchQueryUseCase +import javax.inject.Inject + +class RemoveSearchQueryUseCaseImpl @Inject constructor(private val placeRepository: PlaceRepository) : + RemoveSearchQueryUseCase { + override suspend fun invoke(query: String) { + placeRepository.removeSearchQuery(query) + } + +} \ No newline at end of file diff --git a/app/src/main/java/campus/tech/kakao/map/domain/usecaseImpl/SaveLastPlaceUseCaseImpl.kt b/app/src/main/java/campus/tech/kakao/map/domain/usecaseImpl/SaveLastPlaceUseCaseImpl.kt new file mode 100644 index 00000000..737f7b5a --- /dev/null +++ b/app/src/main/java/campus/tech/kakao/map/domain/usecaseImpl/SaveLastPlaceUseCaseImpl.kt @@ -0,0 +1,13 @@ +package campus.tech.kakao.map.domain.usecaseImpl + +import campus.tech.kakao.map.domain.dto.PlaceVO +import campus.tech.kakao.map.domain.repository.PlaceRepository +import campus.tech.kakao.map.domain.usecase.SaveLastPlaceUseCase +import javax.inject.Inject + +class SaveLastPlaceUseCaseImpl @Inject constructor(private val placeRepository: PlaceRepository): SaveLastPlaceUseCase { + override suspend fun invoke(place: PlaceVO) { + placeRepository.saveLastPlace(place) + } + +} \ No newline at end of file diff --git a/app/src/main/java/campus/tech/kakao/map/domain/usecaseImpl/SaveSearchQueryUseCaseImpl.kt b/app/src/main/java/campus/tech/kakao/map/domain/usecaseImpl/SaveSearchQueryUseCaseImpl.kt new file mode 100644 index 00000000..9189e600 --- /dev/null +++ b/app/src/main/java/campus/tech/kakao/map/domain/usecaseImpl/SaveSearchQueryUseCaseImpl.kt @@ -0,0 +1,14 @@ +package campus.tech.kakao.map.domain.usecaseImpl + +import campus.tech.kakao.map.domain.dto.PlaceVO +import campus.tech.kakao.map.domain.repository.PlaceRepository +import campus.tech.kakao.map.domain.usecase.SaveSearchQueryUseCase +import javax.inject.Inject + +class SaveSearchQueryUseCaseImpl @Inject constructor(private val placeRepository: PlaceRepository) : + SaveSearchQueryUseCase { + override suspend fun invoke(place: PlaceVO) { + placeRepository.saveSearchQuery(place) + } + +} \ No newline at end of file diff --git a/app/src/main/java/campus/tech/kakao/map/presentation/MapActivity.kt b/app/src/main/java/campus/tech/kakao/map/presentation/MapActivity.kt index 483fc52e..0391f0a4 100644 --- a/app/src/main/java/campus/tech/kakao/map/presentation/MapActivity.kt +++ b/app/src/main/java/campus/tech/kakao/map/presentation/MapActivity.kt @@ -5,15 +5,12 @@ import android.graphics.Color import android.os.Bundle import android.util.Log import android.widget.LinearLayout +import androidx.activity.viewModels import androidx.appcompat.app.AppCompatActivity import androidx.cardview.widget.CardView -import androidx.lifecycle.ViewModelProvider import campus.tech.kakao.map.R -import campus.tech.kakao.map.data.repository.PlaceRepositoryImpl -import campus.tech.kakao.map.data.usecase.GetLastPlaceUseCaseImpl -import campus.tech.kakao.map.data.usecase.SaveLastPlaceUseCaseImpl import campus.tech.kakao.map.databinding.ActivityMapBinding -import campus.tech.kakao.map.domain.model.PlaceVO +import campus.tech.kakao.map.domain.dto.PlaceVO import campus.tech.kakao.map.utils.ApiKeyProvider import com.google.android.material.bottomsheet.BottomSheetBehavior import com.kakao.vectormap.KakaoMap @@ -28,14 +25,15 @@ import com.kakao.vectormap.camera.CameraUpdateFactory import com.kakao.vectormap.label.LabelOptions import com.kakao.vectormap.label.LabelStyle import com.kakao.vectormap.label.LabelStyles +import dagger.hilt.android.AndroidEntryPoint - +@AndroidEntryPoint class MapActivity : AppCompatActivity() { private lateinit var binding: ActivityMapBinding private lateinit var mapView: MapView private lateinit var searchBox: CardView private lateinit var kakaoMap: KakaoMap - private lateinit var mapViewModel: MapViewModel + private val mapViewModel: MapViewModel by viewModels() private lateinit var bottomSheetBehavior: BottomSheetBehavior override fun onCreate(savedInstanceState: Bundle?) { @@ -45,8 +43,6 @@ class MapActivity : AppCompatActivity() { setContentView(binding.root) bindingViews() - initializeViewModel() - binding.viewModel = mapViewModel binding.lifecycleOwner = this handleIntentData() @@ -66,14 +62,6 @@ class MapActivity : AppCompatActivity() { } } - private fun initializeViewModel() { - val placeRepository = PlaceRepositoryImpl(context = this) - val factory = MapViewModelFactory( - SaveLastPlaceUseCaseImpl(placeRepository), - GetLastPlaceUseCaseImpl(placeRepository) - ) - mapViewModel = ViewModelProvider(this, factory).get(MapViewModel::class.java) - } private fun setUpMap() { if (mapViewModel.lastPlace.value != null) { @@ -97,6 +85,7 @@ class MapActivity : AppCompatActivity() { } override fun onMapError(error: Exception) { + Log.d("testt", error.message ?: "Unknown error") handleError(error) } }, object : KakaoMapReadyCallback() { diff --git a/app/src/main/java/campus/tech/kakao/map/presentation/MapViewModel.kt b/app/src/main/java/campus/tech/kakao/map/presentation/MapViewModel.kt index aa374a45..d8b6e998 100644 --- a/app/src/main/java/campus/tech/kakao/map/presentation/MapViewModel.kt +++ b/app/src/main/java/campus/tech/kakao/map/presentation/MapViewModel.kt @@ -1,21 +1,27 @@ package campus.tech.kakao.map.presentation -import android.util.Log +import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel -import campus.tech.kakao.map.domain.model.PlaceVO +import androidx.lifecycle.viewModelScope +import campus.tech.kakao.map.domain.dto.PlaceVO import campus.tech.kakao.map.domain.usecase.GetLastPlaceUseCase import campus.tech.kakao.map.domain.usecase.SaveLastPlaceUseCase +import dagger.hilt.android.lifecycle.HiltViewModel +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch import java.io.Serializable +import javax.inject.Inject -class MapViewModel( +@HiltViewModel +class MapViewModel @Inject constructor( private val saveLastPlaceUseCase: SaveLastPlaceUseCase, - private val getLastPlaceUseCase: GetLastPlaceUseCase + private val getLastPlaceUseCase: GetLastPlaceUseCase, ) : ViewModel() { private val _lastPlace = MutableLiveData() - val lastPlace: MutableLiveData get() = _lastPlace + val lastPlace: LiveData get() = _lastPlace init { @@ -24,12 +30,16 @@ class MapViewModel( fun saveLastPlace(place: PlaceVO) { - saveLastPlaceUseCase(place) - _lastPlace.postValue(place) + viewModelScope.launch(Dispatchers.IO) { + saveLastPlaceUseCase(place) + _lastPlace.postValue(place) + } } private fun getLastPlace() { - _lastPlace.value = getLastPlaceUseCase() + viewModelScope.launch(Dispatchers.IO) { + _lastPlace.postValue(getLastPlaceUseCase()) + } } fun setLastPlace(place: Serializable) { diff --git a/app/src/main/java/campus/tech/kakao/map/presentation/MapViewModelFactory.kt b/app/src/main/java/campus/tech/kakao/map/presentation/MapViewModelFactory.kt deleted file mode 100644 index 67b85b82..00000000 --- a/app/src/main/java/campus/tech/kakao/map/presentation/MapViewModelFactory.kt +++ /dev/null @@ -1,18 +0,0 @@ -package campus.tech.kakao.map.presentation - -import androidx.lifecycle.ViewModel -import androidx.lifecycle.ViewModelProvider -import campus.tech.kakao.map.domain.usecase.GetLastPlaceUseCase -import campus.tech.kakao.map.domain.usecase.SaveLastPlaceUseCase - -class MapViewModelFactory( - private val saveLastPlaceUseCase: SaveLastPlaceUseCase, - private val getLastPlaceUseCase: GetLastPlaceUseCase -) : ViewModelProvider.Factory { - override fun create(modelClass: Class): T { - if (modelClass.isAssignableFrom(MapViewModel::class.java)) { - return MapViewModel(saveLastPlaceUseCase, getLastPlaceUseCase) as T - } - throw IllegalArgumentException("Unknown ViewModel class") - } -} diff --git a/app/src/main/java/campus/tech/kakao/map/presentation/PlaceActivity.kt b/app/src/main/java/campus/tech/kakao/map/presentation/PlaceActivity.kt index 0dd5904e..ecc20701 100644 --- a/app/src/main/java/campus/tech/kakao/map/presentation/PlaceActivity.kt +++ b/app/src/main/java/campus/tech/kakao/map/presentation/PlaceActivity.kt @@ -4,20 +4,19 @@ import android.content.Intent import android.os.Bundle import android.text.Editable import android.text.TextWatcher +import android.util.Log import android.widget.TextView +import androidx.activity.viewModels import androidx.appcompat.app.AppCompatActivity -import androidx.lifecycle.ViewModelProvider import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView -import campus.tech.kakao.map.data.repository.PlaceRepositoryImpl -import campus.tech.kakao.map.data.usecase.*; import campus.tech.kakao.map.databinding.ActivityPlaceBinding -import campus.tech.kakao.map.domain.model.PlaceVO -import com.kakao.vectormap.LatLng -import com.kakao.vectormap.camera.CameraPosition +import campus.tech.kakao.map.domain.dto.PlaceVO +import dagger.hilt.android.AndroidEntryPoint +@AndroidEntryPoint class PlaceActivity : AppCompatActivity() { - private lateinit var placeViewModel: PlaceViewModel + private val placeViewModel: PlaceViewModel by viewModels() private lateinit var placeAdapter: PlaceAdapter private lateinit var historyAdapter: SearchHistoryAdapter @@ -29,12 +28,13 @@ class PlaceActivity : AppCompatActivity() { binding = ActivityPlaceBinding.inflate(layoutInflater) setContentView(binding.root) - initializeViewModel() initializeAdapters() initializeRecyclerView() setUpSearchEditText() setUpRemoveButton() + + observeViewModel() } private fun showEmptyMessage() { @@ -52,36 +52,25 @@ class PlaceActivity : AppCompatActivity() { placeAdapter.updateData(places) } + private fun updateUI(places: List?) { + if (places.isNullOrEmpty()) { + showEmptyMessage() + } else { + showRecyclerView(places!!) + } + } - private fun initializeViewModel() { - val placeRepository = PlaceRepositoryImpl(context = this) - - placeViewModel = ViewModelProvider( - this, - PlaceViewModelFactory( - getSearchPlacesUseCase = GetSearchPlacesUseCaseImpl(placeRepository), - saveSearchQueryUseCase = SaveSearchQueryUseCaseImpl(placeRepository), - getSearchHistoryUseCase = GetSearchHistoryUseCaseImpl(placeRepository), - removeSearchQueryUseCase = RemoveSearchQueryUseCaseImpl(placeRepository), - ) - )[PlaceViewModel::class.java] - + private fun observeViewModel() { placeViewModel.places.observe(this) { places -> updateUI(places) + } placeViewModel.searchHistory.observe(this) { history -> historyAdapter.updateData(history) } - placeViewModel.loadSearchHistory() - } - private fun updateUI(places: List) { - if (places.isEmpty()) { - showEmptyMessage() - } else { - showRecyclerView(places) - } + placeViewModel.loadSearchHistory() } private fun initializeRecyclerView() { @@ -94,7 +83,9 @@ class PlaceActivity : AppCompatActivity() { } private fun initializeAdapters() { + Log.d("testt","initializeAdapters") placeAdapter = PlaceAdapter { place -> + Log.d("testt", "place $place") placeViewModel.saveSearchQuery(place) sendPositiontoMap(place) } @@ -105,6 +96,7 @@ class PlaceActivity : AppCompatActivity() { placeViewModel.removeSearchQuery(query) }, onItemClick = { query -> + Log.d("testt", "search $query") binding.searchEditText.setText(query) placeViewModel.searchPlaces(query) } diff --git a/app/src/main/java/campus/tech/kakao/map/presentation/PlaceAdapter.kt b/app/src/main/java/campus/tech/kakao/map/presentation/PlaceAdapter.kt index 9f112d80..e33b8751 100644 --- a/app/src/main/java/campus/tech/kakao/map/presentation/PlaceAdapter.kt +++ b/app/src/main/java/campus/tech/kakao/map/presentation/PlaceAdapter.kt @@ -5,7 +5,7 @@ import android.view.View import android.view.ViewGroup import androidx.recyclerview.widget.RecyclerView import campus.tech.kakao.map.databinding.PlaceItemBinding -import campus.tech.kakao.map.domain.model.PlaceVO +import campus.tech.kakao.map.domain.dto.PlaceVO class PlaceAdapter( private val onItemClick: (PlaceVO) -> Unit, diff --git a/app/src/main/java/campus/tech/kakao/map/presentation/PlaceViewModel.kt b/app/src/main/java/campus/tech/kakao/map/presentation/PlaceViewModel.kt index 85621ee0..b12ac8cc 100644 --- a/app/src/main/java/campus/tech/kakao/map/presentation/PlaceViewModel.kt +++ b/app/src/main/java/campus/tech/kakao/map/presentation/PlaceViewModel.kt @@ -4,40 +4,53 @@ import campus.tech.kakao.map.domain.usecase.* import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel -import campus.tech.kakao.map.domain.model.PlaceVO +import androidx.lifecycle.viewModelScope +import campus.tech.kakao.map.domain.dto.PlaceVO import com.kakao.vectormap.LatLng +import dagger.hilt.android.lifecycle.HiltViewModel +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch +import javax.inject.Inject -class PlaceViewModel( +@HiltViewModel +class PlaceViewModel @Inject constructor( private val getSearchPlacesUseCase: GetSearchPlacesUseCase, private val saveSearchQueryUseCase: SaveSearchQueryUseCase, private val getSearchHistoryUseCase: GetSearchHistoryUseCase, private val removeSearchQueryUseCase: RemoveSearchQueryUseCase, ) : ViewModel() { - private val _places = MutableLiveData>() - val places: LiveData> get() = _places + private val _places = MutableLiveData?>() + val places: MutableLiveData?> get() = _places private val _searchHistory = MutableLiveData>() val searchHistory: LiveData> get() = _searchHistory fun searchPlaces(query: String) { - getSearchPlacesUseCase(query) { - _places.postValue(it) + viewModelScope.launch(Dispatchers.IO) { + val places = getSearchPlacesUseCase(query) + _places.postValue(places) } } fun saveSearchQuery(place: PlaceVO) { - saveSearchQueryUseCase(place) - loadSearchHistory() + viewModelScope.launch(Dispatchers.IO) { + saveSearchQueryUseCase(place) + loadSearchHistory() + } } fun loadSearchHistory() { - val history = getSearchHistoryUseCase() - _searchHistory.postValue(history.toList()) + viewModelScope.launch(Dispatchers.IO) { + val history = getSearchHistoryUseCase() + _searchHistory.postValue(history.toList()) + } } fun removeSearchQuery(query: String) { - removeSearchQueryUseCase(query) - loadSearchHistory() + viewModelScope.launch(Dispatchers.IO) { + removeSearchQueryUseCase(query) + loadSearchHistory() + } } fun getPlaceLocation(place: PlaceVO): LatLng { diff --git a/app/src/main/java/campus/tech/kakao/map/presentation/PlaceViewModelFactory.kt b/app/src/main/java/campus/tech/kakao/map/presentation/PlaceViewModelFactory.kt deleted file mode 100644 index e24fb510..00000000 --- a/app/src/main/java/campus/tech/kakao/map/presentation/PlaceViewModelFactory.kt +++ /dev/null @@ -1,24 +0,0 @@ -package campus.tech.kakao.map.presentation - -import androidx.lifecycle.ViewModel -import androidx.lifecycle.ViewModelProvider -import campus.tech.kakao.map.domain.usecase.*; - -class PlaceViewModelFactory(private val getSearchPlacesUseCase: GetSearchPlacesUseCase, - private val saveSearchQueryUseCase: SaveSearchQueryUseCase, - private val getSearchHistoryUseCase: GetSearchHistoryUseCase, - private val removeSearchQueryUseCase: RemoveSearchQueryUseCase -) : - ViewModelProvider.Factory { - override fun create(modelClass: Class): T { - if (modelClass.isAssignableFrom(PlaceViewModel::class.java)) { - return PlaceViewModel( - getSearchPlacesUseCase, - saveSearchQueryUseCase, - getSearchHistoryUseCase, - removeSearchQueryUseCase - ) as T - } - throw IllegalArgumentException("Unknown ViewModel class") - } -} diff --git a/app/src/main/java/campus/tech/kakao/map/utils/ApiKeyProvider.kt b/app/src/main/java/campus/tech/kakao/map/utils/ApiKeyProvider.kt index c8fd7a58..31d869d4 100644 --- a/app/src/main/java/campus/tech/kakao/map/utils/ApiKeyProvider.kt +++ b/app/src/main/java/campus/tech/kakao/map/utils/ApiKeyProvider.kt @@ -2,7 +2,6 @@ package campus.tech.kakao.map.utils import campus.tech.kakao.map.BuildConfig - object ApiKeyProvider { val KAKAO_REST_API_KEY = "KakaoAK " + BuildConfig.KAKAO_REST_API_KEY val KAKAO_API_KEY = BuildConfig.KAKAO_API_KEY diff --git a/app/src/main/res/layout/activity_map.xml b/app/src/main/res/layout/activity_map.xml index e42378b8..9dbdedaf 100644 --- a/app/src/main/res/layout/activity_map.xml +++ b/app/src/main/res/layout/activity_map.xml @@ -75,7 +75,7 @@ android:layout_height="wrap_content" android:layout_marginLeft="10dp" android:layout_marginBottom="10dp" - android:text="@{viewModel.lastPlace.placeName}" + android:text="${viewModel.lastPlace.placeName}" android:textSize="28sp" android:textStyle="bold" /> @@ -84,7 +84,7 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginLeft="10dp" - android:text="@{viewModel.lastPlace.addressName}" + android:text="viewModel.lastPlace.addressName" android:textSize="19sp" /> diff --git a/app/src/main/res/layout/place_item.xml b/app/src/main/res/layout/place_item.xml index a8b0aca3..2f0ca6e2 100644 --- a/app/src/main/res/layout/place_item.xml +++ b/app/src/main/res/layout/place_item.xml @@ -4,7 +4,7 @@ + type="campus.tech.kakao.map.domain.dto.PlaceVO" /> @@ -15,6 +15,7 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal" + android:onClick="@{clickListener}" android:padding="8dp">