Skip to content

Commit

Permalink
충남대 Android_전영주 5주차 과제 STEP 1 (피드백 반영) (#30)
Browse files Browse the repository at this point in the history
* 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 <[email protected]>
  • Loading branch information
aengzu and MyStoryG authored Jul 26, 2024
1 parent da1570d commit 6aa7879
Show file tree
Hide file tree
Showing 52 changed files with 522 additions and 356 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
3 changes: 3 additions & 0 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">

<uses-permission android:name="android.permission.INTERNET" />

<application
android:name=".MyApplication"
android:allowBackup="true"
android:dataExtractionRules="@xml/data_extraction_rules"
android:fullBackupContent="@xml/backup_rules"
Expand Down
8 changes: 8 additions & 0 deletions app/src/main/java/campus/tech/kakao/map/MyApplication.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package campus.tech.kakao.map

import android.app.Application
import dagger.hilt.android.HiltAndroidApp

@HiltAndroidApp
class MyApplication : Application() {
}
61 changes: 0 additions & 61 deletions app/src/main/java/campus/tech/kakao/map/data/PreferenceHelper.kt

This file was deleted.

Original file line number Diff line number Diff line change
@@ -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
}
Original file line number Diff line number Diff line change
@@ -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<SearchQueryEntity>

@Delete
fun delete(searchQueryEntity: SearchQueryEntity)

@Insert(onConflict = OnConflictStrategy.REPLACE)
fun insert(searchQueryEntity: SearchQueryEntity)
}
Original file line number Diff line number Diff line change
@@ -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)
}
Original file line number Diff line number Diff line change
@@ -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
)
Original file line number Diff line number Diff line change
@@ -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,
)
Original file line number Diff line number Diff line change
@@ -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,
Expand Down
Original file line number Diff line number Diff line change
@@ -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

Expand Down
Original file line number Diff line number Diff line change
@@ -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,
Expand Down
Original file line number Diff line number Diff line change
@@ -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()
}
}

}
Original file line number Diff line number Diff line change
@@ -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

Expand Down
Original file line number Diff line number Diff line change
@@ -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
Expand Down

This file was deleted.

Loading

0 comments on commit 6aa7879

Please sign in to comment.