From 9fb7585a58c5113a136ceb4d580fa7720b43dab6 Mon Sep 17 00:00:00 2001 From: fiveJinw Date: Tue, 2 Jul 2024 13:12:06 +0900 Subject: [PATCH 01/14] docs : Update README.md --- README.md | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index df2a6477..8dfb3a0a 100644 --- a/README.md +++ b/README.md @@ -1 +1,9 @@ -# android-map-keyword +# 2주차 - android-map-keyword +## step1 구현할 기능 목록 + +**UI 관련 기능** +- [ ] 검색어를 입력할 수 있는 칸 구현 +- [ ] 검색 결과를 표시할 수 있는 칸 구현 + +**DB 관련 기능** +- [ ] 장소의 이름, 장소의 위치. 장소 카테고리를 저장할 수 있는 데이터베이스 구현 From 3228d66bef1c6b66c0763b92557fc77e889660c9 Mon Sep 17 00:00:00 2001 From: fiveJinw Date: Tue, 2 Jul 2024 15:20:04 +0900 Subject: [PATCH 02/14] style : Add keywords input field to mainActivity.xml --- README.md | 4 ++-- app/src/main/res/layout/activity_main.xml | 25 +++++++++++++++++------ app/src/main/res/values/strings.xml | 1 + 3 files changed, 22 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 8dfb3a0a..69c0a281 100644 --- a/README.md +++ b/README.md @@ -2,8 +2,8 @@ ## step1 구현할 기능 목록 **UI 관련 기능** -- [ ] 검색어를 입력할 수 있는 칸 구현 +- [x] 검색어를 입력할 수 있는 칸 구현 - [ ] 검색 결과를 표시할 수 있는 칸 구현 **DB 관련 기능** -- [ ] 장소의 이름, 장소의 위치. 장소 카테고리를 저장할 수 있는 데이터베이스 구현 +- [ ] 장소의 이름, 장소의 위치. 장소 카테고리를 저장할 수 있는 데이터베이스 구 \ No newline at end of file diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index 24d17df2..0da47c12 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -7,13 +7,26 @@ android:layout_height="match_parent" tools:context=".MainActivity"> - + app:layout_constraintEnd_toEndOf="parent" + android:hint="@string/search_hint" + android:layout_marginHorizontal="10dp" + android:layout_marginTop="10dp" + android:paddingHorizontal="10dp" + /> + diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index e5ba5b9c..6dd5ecce 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -1,3 +1,4 @@ Map + 검색어를 입력해 주세요. \ No newline at end of file From 924909770bf517803c84fd2a4f12bae360e5621f Mon Sep 17 00:00:00 2001 From: fiveJinw Date: Tue, 2 Jul 2024 15:49:21 +0900 Subject: [PATCH 03/14] style : Add result recyclerView to mainActivity.xml --- app/src/main/res/layout/activity_main.xml | 23 +++++++++++++++++++++++ app/src/main/res/values/strings.xml | 1 + 2 files changed, 24 insertions(+) diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index 0da47c12..9b09b918 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -29,4 +29,27 @@ android:layout_marginEnd="20dp" android:src="@android:drawable/ic_menu_close_clear_cancel"/> + + + + diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 6dd5ecce..290224da 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -1,4 +1,5 @@ Map 검색어를 입력해 주세요. + 검색 결과가 없습니다. \ No newline at end of file From 8ee5a1eb19d75ba043d19d313bd6edd89b83d1e2 Mon Sep 17 00:00:00 2001 From: fiveJinw Date: Tue, 2 Jul 2024 15:51:00 +0900 Subject: [PATCH 04/14] docs : Update README.md --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 69c0a281..32ffdd29 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,8 @@ **UI 관련 기능** - [x] 검색어를 입력할 수 있는 칸 구현 -- [ ] 검색 결과를 표시할 수 있는 칸 구현 +- [x] 검색 결과를 표시할 수 있는 칸 구현 +- [ ] 저장된 검색 결과를 표시할 수 있는 칸 구현 **DB 관련 기능** - [ ] 장소의 이름, 장소의 위치. 장소 카테고리를 저장할 수 있는 데이터베이스 구 \ No newline at end of file From 1936a12258ed58b9dbae2f9022911dfb40584e08 Mon Sep 17 00:00:00 2001 From: fiveJinw Date: Tue, 2 Jul 2024 15:56:14 +0900 Subject: [PATCH 05/14] style : Add saved keywords recyclerView to activity_main.xml --- app/src/main/res/layout/activity_main.xml | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index 9b09b918..9fad75c2 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -29,11 +29,22 @@ android:layout_marginEnd="20dp" android:src="@android:drawable/ic_menu_close_clear_cancel"/> + + Date: Wed, 3 Jul 2024 15:03:47 +0900 Subject: [PATCH 06/14] feat : Add feature that read and write db --- .../campus/tech/kakao/map/MainActivity.kt | 3 + .../main/java/campus/tech/kakao/map/Place.kt | 7 ++ .../campus/tech/kakao/map/PlaceContract.kt | 12 ++++ .../campus/tech/kakao/map/PlaceDBHelper.kt | 72 +++++++++++++++++++ 4 files changed, 94 insertions(+) create mode 100644 app/src/main/java/campus/tech/kakao/map/Place.kt create mode 100644 app/src/main/java/campus/tech/kakao/map/PlaceContract.kt create mode 100644 app/src/main/java/campus/tech/kakao/map/PlaceDBHelper.kt diff --git a/app/src/main/java/campus/tech/kakao/map/MainActivity.kt b/app/src/main/java/campus/tech/kakao/map/MainActivity.kt index 95b43803..954e6cd3 100644 --- a/app/src/main/java/campus/tech/kakao/map/MainActivity.kt +++ b/app/src/main/java/campus/tech/kakao/map/MainActivity.kt @@ -7,5 +7,8 @@ class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) + val dbHelper = PlaceDBHelper(this) +// dbHelper.insertDummyData() + dbHelper.readData() } } diff --git a/app/src/main/java/campus/tech/kakao/map/Place.kt b/app/src/main/java/campus/tech/kakao/map/Place.kt new file mode 100644 index 00000000..6c122a8b --- /dev/null +++ b/app/src/main/java/campus/tech/kakao/map/Place.kt @@ -0,0 +1,7 @@ +package campus.tech.kakao.map + +data class Place( + val name : String, + val location : String, + val category : String +) \ No newline at end of file diff --git a/app/src/main/java/campus/tech/kakao/map/PlaceContract.kt b/app/src/main/java/campus/tech/kakao/map/PlaceContract.kt new file mode 100644 index 00000000..5a282bbf --- /dev/null +++ b/app/src/main/java/campus/tech/kakao/map/PlaceContract.kt @@ -0,0 +1,12 @@ +package campus.tech.kakao.map + +import android.provider.BaseColumns + +object PlaceContract{ + object PlaceEntry : BaseColumns { + const val TABLE_NAME = "PLACE" + const val COLUMN_NAME = "NAME" + const val COLUMN_LOCATION = "LOCATION" + const val COLUMN_CATEGORY = "CATEGORY" + } +} \ No newline at end of file diff --git a/app/src/main/java/campus/tech/kakao/map/PlaceDBHelper.kt b/app/src/main/java/campus/tech/kakao/map/PlaceDBHelper.kt new file mode 100644 index 00000000..25b320f5 --- /dev/null +++ b/app/src/main/java/campus/tech/kakao/map/PlaceDBHelper.kt @@ -0,0 +1,72 @@ +package campus.tech.kakao.map + +import android.content.ContentValues +import android.content.Context +import android.database.sqlite.SQLiteDatabase +import android.database.sqlite.SQLiteOpenHelper +import android.util.Log + + + +class PlaceDBHelper(context:Context) : SQLiteOpenHelper(context, "place.db", null, 1){ + override fun onCreate(db: SQLiteDatabase?) { + db?.execSQL("CREATE TABLE " + + "${PlaceContract.PlaceEntry.TABLE_NAME}( " + + " ${PlaceContract.PlaceEntry.COLUMN_NAME} varchar(60) not null ," + + " ${PlaceContract.PlaceEntry.COLUMN_LOCATION} varchar(255) not null, " + + " ${PlaceContract.PlaceEntry.COLUMN_CATEGORY} varchar(30) );" + ) + } + + override fun onUpgrade(db: SQLiteDatabase?, oldVersion: Int, newVersion: Int) { + db?.execSQL("DROP TABLE IF EXISTS ${PlaceContract.PlaceEntry.TABLE_NAME};") + onCreate(db) + } + + fun insertDummyData(){ + val name = "카페" + val category = "카페" + val location = "서울 성동구 성수동" + for(i in 1..10){ + insertData(name + i, location + i, category) + } + readData() + } + + fun insertData(name: String, location: String, category: String) { + val db = this.writableDatabase + val values = ContentValues().apply { + put(PlaceContract.PlaceEntry.COLUMN_NAME, name) + put(PlaceContract.PlaceEntry.COLUMN_LOCATION, location) + put(PlaceContract.PlaceEntry.COLUMN_CATEGORY, category) + } + db.insert(PlaceContract.PlaceEntry.TABLE_NAME, null, values) + } + + fun readData() :MutableList{ + val rDb = this.readableDatabase + + val cursor = rDb.rawQuery("SELECT * FROM ${PlaceContract.PlaceEntry.TABLE_NAME};", null) + + val result = mutableListOf() + + while (cursor.moveToNext()) { + val place = Place( + cursor.getString( + cursor.getColumnIndexOrThrow(PlaceContract.PlaceEntry.COLUMN_NAME) + ), + cursor.getString( + cursor.getColumnIndexOrThrow(PlaceContract.PlaceEntry.COLUMN_LOCATION) + ), + cursor.getString( + cursor.getColumnIndexOrThrow(PlaceContract.PlaceEntry.COLUMN_CATEGORY) + ) + ) + Log.d("readData", "이름 = ${place.name}, 위치 = ${place.location}, 분류 = ${place.category}") + result.add(place) + } + + cursor.close() + return result + } +} \ No newline at end of file From 25408b80446be770983387c9232e079cfe30b101 Mon Sep 17 00:00:00 2001 From: fiveJinw Date: Wed, 3 Jul 2024 19:08:05 +0900 Subject: [PATCH 07/14] refactor : using MVVM pattern --- app/src/main/AndroidManifest.xml | 2 +- .../campus/tech/kakao/map/MainActivity.kt | 14 -------- .../tech/kakao/map/{ => db}/PlaceContract.kt | 2 +- .../tech/kakao/map/{ => db}/PlaceDBHelper.kt | 30 +++------------- .../tech/kakao/map/{ => model}/Place.kt | 2 +- .../tech/kakao/map/repository/Repository.kt | 36 +++++++++++++++++++ .../tech/kakao/map/view/MainActivity.kt | 21 +++++++++++ .../map/viewmodel/MainActivityViewModel.kt | 10 ++++++ .../kakao/map/viewmodel/ViewModelFactory.kt | 14 ++++++++ app/src/main/res/layout/activity_main.xml | 2 +- 10 files changed, 89 insertions(+), 44 deletions(-) delete mode 100644 app/src/main/java/campus/tech/kakao/map/MainActivity.kt rename app/src/main/java/campus/tech/kakao/map/{ => db}/PlaceContract.kt (89%) rename app/src/main/java/campus/tech/kakao/map/{ => db}/PlaceDBHelper.kt (62%) rename app/src/main/java/campus/tech/kakao/map/{ => model}/Place.kt (72%) create mode 100644 app/src/main/java/campus/tech/kakao/map/repository/Repository.kt create mode 100644 app/src/main/java/campus/tech/kakao/map/view/MainActivity.kt create mode 100644 app/src/main/java/campus/tech/kakao/map/viewmodel/MainActivityViewModel.kt create mode 100644 app/src/main/java/campus/tech/kakao/map/viewmodel/ViewModelFactory.kt diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 6bca2f54..a668b40d 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -13,7 +13,7 @@ android:theme="@style/Theme.Map" tools:targetApi="31"> diff --git a/app/src/main/java/campus/tech/kakao/map/MainActivity.kt b/app/src/main/java/campus/tech/kakao/map/MainActivity.kt deleted file mode 100644 index 954e6cd3..00000000 --- a/app/src/main/java/campus/tech/kakao/map/MainActivity.kt +++ /dev/null @@ -1,14 +0,0 @@ -package campus.tech.kakao.map - -import android.os.Bundle -import androidx.appcompat.app.AppCompatActivity - -class MainActivity : AppCompatActivity() { - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - setContentView(R.layout.activity_main) - val dbHelper = PlaceDBHelper(this) -// dbHelper.insertDummyData() - dbHelper.readData() - } -} diff --git a/app/src/main/java/campus/tech/kakao/map/PlaceContract.kt b/app/src/main/java/campus/tech/kakao/map/db/PlaceContract.kt similarity index 89% rename from app/src/main/java/campus/tech/kakao/map/PlaceContract.kt rename to app/src/main/java/campus/tech/kakao/map/db/PlaceContract.kt index 5a282bbf..8c61eac3 100644 --- a/app/src/main/java/campus/tech/kakao/map/PlaceContract.kt +++ b/app/src/main/java/campus/tech/kakao/map/db/PlaceContract.kt @@ -1,4 +1,4 @@ -package campus.tech.kakao.map +package campus.tech.kakao.map.db import android.provider.BaseColumns diff --git a/app/src/main/java/campus/tech/kakao/map/PlaceDBHelper.kt b/app/src/main/java/campus/tech/kakao/map/db/PlaceDBHelper.kt similarity index 62% rename from app/src/main/java/campus/tech/kakao/map/PlaceDBHelper.kt rename to app/src/main/java/campus/tech/kakao/map/db/PlaceDBHelper.kt index 25b320f5..91da9739 100644 --- a/app/src/main/java/campus/tech/kakao/map/PlaceDBHelper.kt +++ b/app/src/main/java/campus/tech/kakao/map/db/PlaceDBHelper.kt @@ -1,11 +1,10 @@ -package campus.tech.kakao.map +package campus.tech.kakao.map.db import android.content.ContentValues import android.content.Context +import android.database.Cursor import android.database.sqlite.SQLiteDatabase import android.database.sqlite.SQLiteOpenHelper -import android.util.Log - class PlaceDBHelper(context:Context) : SQLiteOpenHelper(context, "place.db", null, 1){ @@ -43,30 +42,9 @@ class PlaceDBHelper(context:Context) : SQLiteOpenHelper(context, "place.db", nul db.insert(PlaceContract.PlaceEntry.TABLE_NAME, null, values) } - fun readData() :MutableList{ + fun readData(): Cursor { val rDb = this.readableDatabase - val cursor = rDb.rawQuery("SELECT * FROM ${PlaceContract.PlaceEntry.TABLE_NAME};", null) - - val result = mutableListOf() - - while (cursor.moveToNext()) { - val place = Place( - cursor.getString( - cursor.getColumnIndexOrThrow(PlaceContract.PlaceEntry.COLUMN_NAME) - ), - cursor.getString( - cursor.getColumnIndexOrThrow(PlaceContract.PlaceEntry.COLUMN_LOCATION) - ), - cursor.getString( - cursor.getColumnIndexOrThrow(PlaceContract.PlaceEntry.COLUMN_CATEGORY) - ) - ) - Log.d("readData", "이름 = ${place.name}, 위치 = ${place.location}, 분류 = ${place.category}") - result.add(place) - } - - cursor.close() - return result + return rDb.rawQuery("SELECT * FROM ${PlaceContract.PlaceEntry.TABLE_NAME};", null) } } \ No newline at end of file diff --git a/app/src/main/java/campus/tech/kakao/map/Place.kt b/app/src/main/java/campus/tech/kakao/map/model/Place.kt similarity index 72% rename from app/src/main/java/campus/tech/kakao/map/Place.kt rename to app/src/main/java/campus/tech/kakao/map/model/Place.kt index 6c122a8b..82df63f2 100644 --- a/app/src/main/java/campus/tech/kakao/map/Place.kt +++ b/app/src/main/java/campus/tech/kakao/map/model/Place.kt @@ -1,4 +1,4 @@ -package campus.tech.kakao.map +package campus.tech.kakao.map.model data class Place( val name : String, diff --git a/app/src/main/java/campus/tech/kakao/map/repository/Repository.kt b/app/src/main/java/campus/tech/kakao/map/repository/Repository.kt new file mode 100644 index 00000000..8b1e5160 --- /dev/null +++ b/app/src/main/java/campus/tech/kakao/map/repository/Repository.kt @@ -0,0 +1,36 @@ +package campus.tech.kakao.map.repository + +import android.util.Log +import campus.tech.kakao.map.db.PlaceContract +import campus.tech.kakao.map.db.PlaceDBHelper +import campus.tech.kakao.map.model.Place + +class Repository (val dbHelper: PlaceDBHelper){ + fun getAllPlace() : MutableList{ + val cursor = dbHelper.readData() + val result = mutableListOf() + + while (cursor.moveToNext()) { + val place = Place( + cursor.getString( + cursor.getColumnIndexOrThrow(PlaceContract.PlaceEntry.COLUMN_NAME) + ), + cursor.getString( + cursor.getColumnIndexOrThrow(PlaceContract.PlaceEntry.COLUMN_LOCATION) + ), + cursor.getString( + cursor.getColumnIndexOrThrow(PlaceContract.PlaceEntry.COLUMN_CATEGORY) + ) + ) + Log.d("readData", "이름 = ${place.name}, 위치 = ${place.location}, 분류 = ${place.category}") + result.add(place) + } + + cursor.close() + return result + } + + fun writePlace(place: Place){ + dbHelper.insertData(place.name, place.location, place.category) + } +} \ No newline at end of file diff --git a/app/src/main/java/campus/tech/kakao/map/view/MainActivity.kt b/app/src/main/java/campus/tech/kakao/map/view/MainActivity.kt new file mode 100644 index 00000000..8eb9bfcc --- /dev/null +++ b/app/src/main/java/campus/tech/kakao/map/view/MainActivity.kt @@ -0,0 +1,21 @@ +package campus.tech.kakao.map.view + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import androidx.lifecycle.ViewModelProvider +import campus.tech.kakao.map.db.PlaceDBHelper +import campus.tech.kakao.map.R +import campus.tech.kakao.map.repository.Repository +import campus.tech.kakao.map.viewmodel.MainActivityViewModel +import campus.tech.kakao.map.viewmodel.ViewModelFactory + +class MainActivity : AppCompatActivity() { + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setContentView(R.layout.activity_main) + val dbHelper = PlaceDBHelper(this) + val repository = Repository(dbHelper) + val viewModel = ViewModelProvider(this, ViewModelFactory(repository))[MainActivityViewModel::class.java] + viewModel.getPlace() + } +} diff --git a/app/src/main/java/campus/tech/kakao/map/viewmodel/MainActivityViewModel.kt b/app/src/main/java/campus/tech/kakao/map/viewmodel/MainActivityViewModel.kt new file mode 100644 index 00000000..21b611bb --- /dev/null +++ b/app/src/main/java/campus/tech/kakao/map/viewmodel/MainActivityViewModel.kt @@ -0,0 +1,10 @@ +package campus.tech.kakao.map.viewmodel + +import androidx.lifecycle.ViewModel +import campus.tech.kakao.map.repository.Repository + +class MainActivityViewModel (private val repository: Repository) : ViewModel() { + fun getPlace(){ + repository.getAllPlace() + } +} \ No newline at end of file diff --git a/app/src/main/java/campus/tech/kakao/map/viewmodel/ViewModelFactory.kt b/app/src/main/java/campus/tech/kakao/map/viewmodel/ViewModelFactory.kt new file mode 100644 index 00000000..c3f19288 --- /dev/null +++ b/app/src/main/java/campus/tech/kakao/map/viewmodel/ViewModelFactory.kt @@ -0,0 +1,14 @@ +package campus.tech.kakao.map.viewmodel + +import androidx.lifecycle.ViewModel +import androidx.lifecycle.ViewModelProvider +import campus.tech.kakao.map.repository.Repository + +class ViewModelFactory(private val repository: Repository) : ViewModelProvider.Factory { + override fun create(modelClass: Class): T { + if(modelClass.isAssignableFrom(MainActivityViewModel::class.java)){ + return MainActivityViewModel(repository) as T + } + throw IllegalArgumentException("unKnown ViewModel class") + } +} \ No newline at end of file diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index 9fad75c2..0290fdd4 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -5,7 +5,7 @@ android:id="@+id/main" android:layout_width="match_parent" android:layout_height="match_parent" - tools:context=".MainActivity"> + tools:context=".view.MainActivity"> Date: Thu, 4 Jul 2024 14:29:34 +0900 Subject: [PATCH 08/14] docs : Update README.md file with step2: --- README.md | 17 +++++++++++++++-- .../campus/tech/kakao/map/db/PlaceDBHelper.kt | 1 - 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 32ffdd29..6de92dae 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,20 @@ **UI 관련 기능** - [x] 검색어를 입력할 수 있는 칸 구현 - [x] 검색 결과를 표시할 수 있는 칸 구현 -- [ ] 저장된 검색 결과를 표시할 수 있는 칸 구현 +- [x] 저장된 검색 결과를 표시할 수 있는 칸 구현 **DB 관련 기능** -- [ ] 장소의 이름, 장소의 위치. 장소 카테고리를 저장할 수 있는 데이터베이스 구 \ No newline at end of file +- [x] 장소의 이름, 장소의 위치. 장소 카테고리를 저장할 수 있는 데이터베이스 구현 + +--------------------------- +## step2 구현할 기능 목록 + + +**검색 관련 기능** +- [ ] 검색어를 입력하면 검색 결과 목록을 스크롤이 가능하도록 띄우는 기능 +- [ ] X를 누르면 입력한 검색어를 삭제하는 기능 + +**저장 관련 기능** +- [ ] 검색 결과 목록중 하나를 클릭하면 저장하는 기능 +- [ ] 저장된 목록을 검색창 밑에서 가로 스크롤이 가능하도록 띄우는 기능 +- [ ] 저장된 목록중 X를 누르면 저장된 목록을 삭제하는 기능 diff --git a/app/src/main/java/campus/tech/kakao/map/db/PlaceDBHelper.kt b/app/src/main/java/campus/tech/kakao/map/db/PlaceDBHelper.kt index 91da9739..1e388db0 100644 --- a/app/src/main/java/campus/tech/kakao/map/db/PlaceDBHelper.kt +++ b/app/src/main/java/campus/tech/kakao/map/db/PlaceDBHelper.kt @@ -44,7 +44,6 @@ class PlaceDBHelper(context:Context) : SQLiteOpenHelper(context, "place.db", nul fun readData(): Cursor { val rDb = this.readableDatabase - return rDb.rawQuery("SELECT * FROM ${PlaceContract.PlaceEntry.TABLE_NAME};", null) } } \ No newline at end of file From c3722dd005e1b12b8a0db981180f257bbacbfa27 Mon Sep 17 00:00:00 2001 From: fiveJinw Date: Thu, 4 Jul 2024 21:40:28 +0900 Subject: [PATCH 09/14] feat : Add feature that search place --- .../campus/tech/kakao/map/db/PlaceDBHelper.kt | 9 +- .../tech/kakao/map/repository/Repository.kt | 32 +++++++- .../tech/kakao/map/view/MainActivity.kt | 82 ++++++++++++++++++- .../map/viewmodel/MainActivityViewModel.kt | 13 ++- app/src/main/res/layout/place_item.xml | 60 ++++++++++++++ app/src/main/res/values/colors.xml | 1 + 6 files changed, 189 insertions(+), 8 deletions(-) create mode 100644 app/src/main/res/layout/place_item.xml diff --git a/app/src/main/java/campus/tech/kakao/map/db/PlaceDBHelper.kt b/app/src/main/java/campus/tech/kakao/map/db/PlaceDBHelper.kt index 1e388db0..b1b41e75 100644 --- a/app/src/main/java/campus/tech/kakao/map/db/PlaceDBHelper.kt +++ b/app/src/main/java/campus/tech/kakao/map/db/PlaceDBHelper.kt @@ -23,8 +23,8 @@ class PlaceDBHelper(context:Context) : SQLiteOpenHelper(context, "place.db", nul } fun insertDummyData(){ - val name = "카페" - val category = "카페" + val name = "약국" + val category = "약국" val location = "서울 성동구 성수동" for(i in 1..10){ insertData(name + i, location + i, category) @@ -46,4 +46,9 @@ class PlaceDBHelper(context:Context) : SQLiteOpenHelper(context, "place.db", nul val rDb = this.readableDatabase return rDb.rawQuery("SELECT * FROM ${PlaceContract.PlaceEntry.TABLE_NAME};", null) } + + fun readDataWithCategory(category : String): Cursor { + val rDb = this.readableDatabase + return rDb.rawQuery("SELECT * FROM ${PlaceContract.PlaceEntry.TABLE_NAME} WHERE ${PlaceContract.PlaceEntry.COLUMN_CATEGORY} = '${category}';", null) + } } \ No newline at end of file diff --git a/app/src/main/java/campus/tech/kakao/map/repository/Repository.kt b/app/src/main/java/campus/tech/kakao/map/repository/Repository.kt index 8b1e5160..84c771e0 100644 --- a/app/src/main/java/campus/tech/kakao/map/repository/Repository.kt +++ b/app/src/main/java/campus/tech/kakao/map/repository/Repository.kt @@ -1,6 +1,7 @@ package campus.tech.kakao.map.repository import android.util.Log +import androidx.lifecycle.MutableLiveData import campus.tech.kakao.map.db.PlaceContract import campus.tech.kakao.map.db.PlaceDBHelper import campus.tech.kakao.map.model.Place @@ -8,7 +9,7 @@ import campus.tech.kakao.map.model.Place class Repository (val dbHelper: PlaceDBHelper){ fun getAllPlace() : MutableList{ val cursor = dbHelper.readData() - val result = mutableListOf() + val placeList = mutableListOf() while (cursor.moveToNext()) { val place = Place( @@ -23,14 +24,39 @@ class Repository (val dbHelper: PlaceDBHelper){ ) ) Log.d("readData", "이름 = ${place.name}, 위치 = ${place.location}, 분류 = ${place.category}") - result.add(place) + placeList.add(place) } cursor.close() - return result + return placeList } fun writePlace(place: Place){ dbHelper.insertData(place.name, place.location, place.category) } + + fun getPlaceWithCategory(category : String): MutableList{ + val cursor = dbHelper.readDataWithCategory(category) + val placeList = mutableListOf() + + while (cursor.moveToNext()) { + val place = Place( + cursor.getString( + cursor.getColumnIndexOrThrow(PlaceContract.PlaceEntry.COLUMN_NAME) + ), + cursor.getString( + cursor.getColumnIndexOrThrow(PlaceContract.PlaceEntry.COLUMN_LOCATION) + ), + cursor.getString( + cursor.getColumnIndexOrThrow(PlaceContract.PlaceEntry.COLUMN_CATEGORY) + ) + ) + Log.d("readData", "이름 = ${place.name}, 위치 = ${place.location}, 분류 = ${place.category}") + placeList.add(place) + } + + + cursor.close() + return placeList + } } \ No newline at end of file diff --git a/app/src/main/java/campus/tech/kakao/map/view/MainActivity.kt b/app/src/main/java/campus/tech/kakao/map/view/MainActivity.kt index 8eb9bfcc..064def44 100644 --- a/app/src/main/java/campus/tech/kakao/map/view/MainActivity.kt +++ b/app/src/main/java/campus/tech/kakao/map/view/MainActivity.kt @@ -1,21 +1,99 @@ package campus.tech.kakao.map.view +import android.content.Context import android.os.Bundle +import android.text.Editable +import android.text.TextWatcher +import android.util.Log +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.EditText +import android.widget.TextView import androidx.appcompat.app.AppCompatActivity +import androidx.core.widget.addTextChangedListener +import androidx.lifecycle.LiveData +import androidx.lifecycle.Observer import androidx.lifecycle.ViewModelProvider -import campus.tech.kakao.map.db.PlaceDBHelper +import androidx.recyclerview.widget.LinearLayoutManager +import androidx.recyclerview.widget.RecyclerView +import androidx.recyclerview.widget.RecyclerView.OnChildAttachStateChangeListener import campus.tech.kakao.map.R +import campus.tech.kakao.map.db.PlaceDBHelper +import campus.tech.kakao.map.model.Place import campus.tech.kakao.map.repository.Repository import campus.tech.kakao.map.viewmodel.MainActivityViewModel import campus.tech.kakao.map.viewmodel.ViewModelFactory + class MainActivity : AppCompatActivity() { + lateinit var noResultText : TextView + lateinit var inputSearchField: EditText override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) + noResultText = findViewById(R.id.no_search_result) + val recyclerView = findViewById(R.id.search_result_recyclerView) + inputSearchField = findViewById(R.id.input_search_field) val dbHelper = PlaceDBHelper(this) val repository = Repository(dbHelper) val viewModel = ViewModelProvider(this, ViewModelFactory(repository))[MainActivityViewModel::class.java] - viewModel.getPlace() + + Log.d("testt", viewModel.place.toString()) + viewModel.place.observe(this, Observer { newData -> + Log.d("readData", "데이터 변경 감지") + val place = viewModel.place + Log.d("testt", "place") + place?.let{ + recyclerView.layoutManager = LinearLayoutManager(this) + recyclerView.adapter = RecyclerViewAdapter(place,LayoutInflater.from(this), this) + noResultText.visibility = View.INVISIBLE + } + if(place.value?.isEmpty() == true) noResultText.visibility = View.VISIBLE + }) + + inputSearchField.addTextChangedListener(object : TextWatcher{ + override fun beforeTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) { + } + + override fun onTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) { + } + + override fun afterTextChanged(p0: Editable?) { + val text = inputSearchField.text.toString() + viewModel.getPlaceWithCategory(text) + } + }) + + } } + +class RecyclerViewAdapter( + var placeList: LiveData>, + var inflater: LayoutInflater, + var context: Context +): RecyclerView.Adapter(){ + + inner class PlaceViewHolder(itemView : View) :RecyclerView.ViewHolder(itemView){ + val name = itemView.findViewById(R.id.place_name) + val location = itemView.findViewById(R.id.place_location) + val category = itemView.findViewById(R.id.place_category) + } + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): PlaceViewHolder { + val view = inflater.inflate(R.layout.place_item, parent, false) + Log.d("testt", "onCreateViewHolder") + return PlaceViewHolder(view) + } + + override fun onBindViewHolder(holder: PlaceViewHolder, position: Int) { + holder.name.text = placeList.value?.get(position)?.name ?: "" + holder.location.text = placeList.value?.get(position)?.location ?: "" + holder.category.text = placeList.value?.get(position)?.category ?: "" + } + + override fun getItemCount(): Int { + return placeList.value?.size ?: 0 + } +} \ No newline at end of file diff --git a/app/src/main/java/campus/tech/kakao/map/viewmodel/MainActivityViewModel.kt b/app/src/main/java/campus/tech/kakao/map/viewmodel/MainActivityViewModel.kt index 21b611bb..dfca5909 100644 --- a/app/src/main/java/campus/tech/kakao/map/viewmodel/MainActivityViewModel.kt +++ b/app/src/main/java/campus/tech/kakao/map/viewmodel/MainActivityViewModel.kt @@ -1,10 +1,21 @@ package campus.tech.kakao.map.viewmodel +import androidx.lifecycle.LiveData +import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel +import campus.tech.kakao.map.model.Place import campus.tech.kakao.map.repository.Repository +import java.util.Locale.Category class MainActivityViewModel (private val repository: Repository) : ViewModel() { + private var _place = MutableLiveData>() + val place : LiveData> get() = _place + fun getPlace(){ - repository.getAllPlace() + _place.postValue(repository.getAllPlace()) + } + + fun getPlaceWithCategory(category: String){ + _place.postValue(repository.getPlaceWithCategory(category)) } } \ No newline at end of file diff --git a/app/src/main/res/layout/place_item.xml b/app/src/main/res/layout/place_item.xml new file mode 100644 index 00000000..94f5b65a --- /dev/null +++ b/app/src/main/res/layout/place_item.xml @@ -0,0 +1,60 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml index 768b058a..f1b5bf4d 100644 --- a/app/src/main/res/values/colors.xml +++ b/app/src/main/res/values/colors.xml @@ -2,4 +2,5 @@ #FF000000 #FFFFFFFF + #7C7C7C From 988a64f0ee6418047f95f2fed190c52e6f59e964 Mon Sep 17 00:00:00 2001 From: fiveJinw Date: Fri, 5 Jul 2024 00:14:23 +0900 Subject: [PATCH 10/14] feat : Add feature that delete search field when button is clicked --- .../main/java/campus/tech/kakao/map/view/MainActivity.kt | 6 ++++++ app/src/main/res/layout/activity_main.xml | 2 ++ 2 files changed, 8 insertions(+) diff --git a/app/src/main/java/campus/tech/kakao/map/view/MainActivity.kt b/app/src/main/java/campus/tech/kakao/map/view/MainActivity.kt index 064def44..524e7f17 100644 --- a/app/src/main/java/campus/tech/kakao/map/view/MainActivity.kt +++ b/app/src/main/java/campus/tech/kakao/map/view/MainActivity.kt @@ -9,6 +9,7 @@ import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import android.widget.EditText +import android.widget.ImageView import android.widget.TextView import androidx.appcompat.app.AppCompatActivity import androidx.core.widget.addTextChangedListener @@ -38,6 +39,11 @@ class MainActivity : AppCompatActivity() { val dbHelper = PlaceDBHelper(this) val repository = Repository(dbHelper) val viewModel = ViewModelProvider(this, ViewModelFactory(repository))[MainActivityViewModel::class.java] + val searchDeleteButton = findViewById(R.id.button_X) + searchDeleteButton.setOnClickListener{ + inputSearchField.setText("") + inputSearchField.clearFocus() + } Log.d("testt", viewModel.place.toString()) viewModel.place.observe(this, Observer { newData -> diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index 0290fdd4..56789b64 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -3,6 +3,8 @@ xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/main" + android:focusable="true" + android:focusableInTouchMode="true" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".view.MainActivity"> From 47ccbc49398d98df5f93c1065a42cb084f6156c6 Mon Sep 17 00:00:00 2001 From: fiveJinw Date: Fri, 5 Jul 2024 16:16:08 +0900 Subject: [PATCH 11/14] feat : Add feature that save place info --- .../campus/tech/kakao/map/db/PlaceContract.kt | 5 ++ .../campus/tech/kakao/map/db/PlaceDBHelper.kt | 72 ++++++++++++++----- .../campus/tech/kakao/map/model/SavedPlace.kt | 5 ++ .../{Repository.kt => PlaceRepository.kt} | 9 ++- .../map/repository/SavedPlaceRepository.kt | 39 ++++++++++ .../tech/kakao/map/view/MainActivity.kt | 67 ++++++++++++----- .../map/viewmodel/MainActivityViewModel.kt | 34 ++++++--- .../kakao/map/viewmodel/ViewModelFactory.kt | 12 ++-- app/src/main/res/layout/saved_place_item.xml | 29 ++++++++ 9 files changed, 219 insertions(+), 53 deletions(-) create mode 100644 app/src/main/java/campus/tech/kakao/map/model/SavedPlace.kt rename app/src/main/java/campus/tech/kakao/map/repository/{Repository.kt => PlaceRepository.kt} (87%) create mode 100644 app/src/main/java/campus/tech/kakao/map/repository/SavedPlaceRepository.kt create mode 100644 app/src/main/res/layout/saved_place_item.xml diff --git a/app/src/main/java/campus/tech/kakao/map/db/PlaceContract.kt b/app/src/main/java/campus/tech/kakao/map/db/PlaceContract.kt index 8c61eac3..95147ac8 100644 --- a/app/src/main/java/campus/tech/kakao/map/db/PlaceContract.kt +++ b/app/src/main/java/campus/tech/kakao/map/db/PlaceContract.kt @@ -9,4 +9,9 @@ object PlaceContract{ const val COLUMN_LOCATION = "LOCATION" const val COLUMN_CATEGORY = "CATEGORY" } + + object SavedPlaceEntry : BaseColumns{ + const val TABLE_NAME = "SAVED_PLACE" + const val COLUMN_NAME = "SAVED_NAME" + } } \ No newline at end of file diff --git a/app/src/main/java/campus/tech/kakao/map/db/PlaceDBHelper.kt b/app/src/main/java/campus/tech/kakao/map/db/PlaceDBHelper.kt index b1b41e75..765f94f7 100644 --- a/app/src/main/java/campus/tech/kakao/map/db/PlaceDBHelper.kt +++ b/app/src/main/java/campus/tech/kakao/map/db/PlaceDBHelper.kt @@ -5,34 +5,43 @@ import android.content.Context import android.database.Cursor import android.database.sqlite.SQLiteDatabase import android.database.sqlite.SQLiteOpenHelper +import android.util.Log -class PlaceDBHelper(context:Context) : SQLiteOpenHelper(context, "place.db", null, 1){ +class PlaceDBHelper(context: Context) : SQLiteOpenHelper(context, "place.db", null, 2) { override fun onCreate(db: SQLiteDatabase?) { - db?.execSQL("CREATE TABLE " + - "${PlaceContract.PlaceEntry.TABLE_NAME}( " + - " ${PlaceContract.PlaceEntry.COLUMN_NAME} varchar(60) not null ," + - " ${PlaceContract.PlaceEntry.COLUMN_LOCATION} varchar(255) not null, " + - " ${PlaceContract.PlaceEntry.COLUMN_CATEGORY} varchar(30) );" + db?.execSQL( + "CREATE TABLE " + + "${PlaceContract.PlaceEntry.TABLE_NAME}( " + + " ${PlaceContract.PlaceEntry.COLUMN_NAME} varchar(60) not null ," + + " ${PlaceContract.PlaceEntry.COLUMN_LOCATION} varchar(255) not null, " + + " ${PlaceContract.PlaceEntry.COLUMN_CATEGORY} varchar(30) );" + ) + + db?.execSQL( + "CREATE TABLE " + + "${PlaceContract.SavedPlaceEntry.TABLE_NAME}( " + + " ${PlaceContract.SavedPlaceEntry.COLUMN_NAME} varchar(60) not null);" ) } override fun onUpgrade(db: SQLiteDatabase?, oldVersion: Int, newVersion: Int) { db?.execSQL("DROP TABLE IF EXISTS ${PlaceContract.PlaceEntry.TABLE_NAME};") + db?.execSQL("DROP TABLE IF EXISTS ${PlaceContract.SavedPlaceEntry.TABLE_NAME};") onCreate(db) } - fun insertDummyData(){ - val name = "약국" - val category = "약국" - val location = "서울 성동구 성수동" - for(i in 1..10){ - insertData(name + i, location + i, category) + fun insertDummyData() { + val name = "카페" + val category = "카페" + val location = "서울 농기구 고길동" + for (i in 1..10) { + insertPlaceData(name + i, location + i, category) } - readData() + readPlaceData() } - fun insertData(name: String, location: String, category: String) { + fun insertPlaceData(name: String, location: String, category: String) { val db = this.writableDatabase val values = ContentValues().apply { put(PlaceContract.PlaceEntry.COLUMN_NAME, name) @@ -42,13 +51,42 @@ class PlaceDBHelper(context:Context) : SQLiteOpenHelper(context, "place.db", nul db.insert(PlaceContract.PlaceEntry.TABLE_NAME, null, values) } - fun readData(): Cursor { + fun insertSavedPlaceData(name: String) { + val db = this.writableDatabase + val values = ContentValues().apply { + put(PlaceContract.SavedPlaceEntry.COLUMN_NAME, name) + } + db.insert(PlaceContract.SavedPlaceEntry.TABLE_NAME, null, values) + } + + fun readPlaceData(): Cursor { val rDb = this.readableDatabase return rDb.rawQuery("SELECT * FROM ${PlaceContract.PlaceEntry.TABLE_NAME};", null) } - fun readDataWithCategory(category : String): Cursor { + fun readPlaceDataWithSamedCategory(category: String): Cursor { + val rDb = this.readableDatabase + return rDb.rawQuery( + "SELECT * FROM ${PlaceContract.PlaceEntry.TABLE_NAME} WHERE ${PlaceContract.PlaceEntry.COLUMN_CATEGORY} = '${category}';", + null + ) + } + + fun readSavedPlaceData(): Cursor { + val rDb = this.readableDatabase + return rDb.rawQuery("SELECT * FROM ${PlaceContract.SavedPlaceEntry.TABLE_NAME};", null) + } + + fun readSavedPlaceDataWithSamedName(name: String): Cursor { val rDb = this.readableDatabase - return rDb.rawQuery("SELECT * FROM ${PlaceContract.PlaceEntry.TABLE_NAME} WHERE ${PlaceContract.PlaceEntry.COLUMN_CATEGORY} = '${category}';", null) + return rDb.rawQuery( + "SELECT * FROM ${PlaceContract.SavedPlaceEntry.TABLE_NAME} WHERE ${PlaceContract.SavedPlaceEntry.COLUMN_NAME} = '${name}';", + null + ) + } + + fun deleteSavedPlace(name: String) { + val db = this.writableDatabase + db.delete(PlaceContract.SavedPlaceEntry.TABLE_NAME, "${PlaceContract.SavedPlaceEntry.COLUMN_NAME} = ?", arrayOf(name)) } } \ No newline at end of file diff --git a/app/src/main/java/campus/tech/kakao/map/model/SavedPlace.kt b/app/src/main/java/campus/tech/kakao/map/model/SavedPlace.kt new file mode 100644 index 00000000..be8f2799 --- /dev/null +++ b/app/src/main/java/campus/tech/kakao/map/model/SavedPlace.kt @@ -0,0 +1,5 @@ +package campus.tech.kakao.map.model + +data class SavedPlace( + val name: String +) \ No newline at end of file diff --git a/app/src/main/java/campus/tech/kakao/map/repository/Repository.kt b/app/src/main/java/campus/tech/kakao/map/repository/PlaceRepository.kt similarity index 87% rename from app/src/main/java/campus/tech/kakao/map/repository/Repository.kt rename to app/src/main/java/campus/tech/kakao/map/repository/PlaceRepository.kt index 84c771e0..991451e3 100644 --- a/app/src/main/java/campus/tech/kakao/map/repository/Repository.kt +++ b/app/src/main/java/campus/tech/kakao/map/repository/PlaceRepository.kt @@ -1,14 +1,13 @@ package campus.tech.kakao.map.repository import android.util.Log -import androidx.lifecycle.MutableLiveData import campus.tech.kakao.map.db.PlaceContract import campus.tech.kakao.map.db.PlaceDBHelper import campus.tech.kakao.map.model.Place -class Repository (val dbHelper: PlaceDBHelper){ +class PlaceRepository (val dbHelper: PlaceDBHelper){ fun getAllPlace() : MutableList{ - val cursor = dbHelper.readData() + val cursor = dbHelper.readPlaceData() val placeList = mutableListOf() while (cursor.moveToNext()) { @@ -32,11 +31,11 @@ class Repository (val dbHelper: PlaceDBHelper){ } fun writePlace(place: Place){ - dbHelper.insertData(place.name, place.location, place.category) + dbHelper.insertPlaceData(place.name, place.location, place.category) } fun getPlaceWithCategory(category : String): MutableList{ - val cursor = dbHelper.readDataWithCategory(category) + val cursor = dbHelper.readPlaceDataWithSamedCategory(category) val placeList = mutableListOf() while (cursor.moveToNext()) { diff --git a/app/src/main/java/campus/tech/kakao/map/repository/SavedPlaceRepository.kt b/app/src/main/java/campus/tech/kakao/map/repository/SavedPlaceRepository.kt new file mode 100644 index 00000000..8ce201b4 --- /dev/null +++ b/app/src/main/java/campus/tech/kakao/map/repository/SavedPlaceRepository.kt @@ -0,0 +1,39 @@ +package campus.tech.kakao.map.repository + +import android.util.Log +import campus.tech.kakao.map.db.PlaceContract +import campus.tech.kakao.map.db.PlaceDBHelper +import campus.tech.kakao.map.model.Place +import campus.tech.kakao.map.model.SavedPlace + +class SavedPlaceRepository (val dbHelper: PlaceDBHelper){ + fun getAllSavedPlace() : MutableList{ + val cursor = dbHelper.readSavedPlaceData() + val placeList = mutableListOf() + + while (cursor.moveToNext()) { + val place = SavedPlace( + cursor.getString( + cursor.getColumnIndexOrThrow(PlaceContract.SavedPlaceEntry.COLUMN_NAME) + ) + ) + Log.d("readData", "이름 = ${place.name}") + placeList.add(place) + } + + cursor.close() + return placeList + } + + fun writePlace(place: Place){ + val cursor = dbHelper.readSavedPlaceDataWithSamedName(place.name) + if (cursor.moveToFirst()) { + Log.d("testt", "데이터 중복") + // 입력의 시간순대로 정렬되기 떄문에 레코드 삭제후 다시 집어넣기 + dbHelper.deleteSavedPlace(place.name) + dbHelper.insertSavedPlaceData(place.name) + } else { + dbHelper.insertSavedPlaceData(place.name) + } + } +} \ No newline at end of file diff --git a/app/src/main/java/campus/tech/kakao/map/view/MainActivity.kt b/app/src/main/java/campus/tech/kakao/map/view/MainActivity.kt index 524e7f17..93207a49 100644 --- a/app/src/main/java/campus/tech/kakao/map/view/MainActivity.kt +++ b/app/src/main/java/campus/tech/kakao/map/view/MainActivity.kt @@ -16,20 +16,24 @@ import androidx.core.widget.addTextChangedListener import androidx.lifecycle.LiveData import androidx.lifecycle.Observer import androidx.lifecycle.ViewModelProvider +import androidx.lifecycle.viewmodel.viewModelFactory import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView.OnChildAttachStateChangeListener import campus.tech.kakao.map.R import campus.tech.kakao.map.db.PlaceDBHelper import campus.tech.kakao.map.model.Place -import campus.tech.kakao.map.repository.Repository +import campus.tech.kakao.map.model.SavedPlace +import campus.tech.kakao.map.repository.PlaceRepository +import campus.tech.kakao.map.repository.SavedPlaceRepository import campus.tech.kakao.map.viewmodel.MainActivityViewModel import campus.tech.kakao.map.viewmodel.ViewModelFactory -class MainActivity : AppCompatActivity() { - lateinit var noResultText : TextView +class MainActivity : AppCompatActivity(), OnClickPlaceListener { + lateinit var noResultText: TextView lateinit var inputSearchField: EditText + lateinit var viewModel : MainActivityViewModel override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) @@ -37,10 +41,15 @@ class MainActivity : AppCompatActivity() { val recyclerView = findViewById(R.id.search_result_recyclerView) inputSearchField = findViewById(R.id.input_search_field) val dbHelper = PlaceDBHelper(this) - val repository = Repository(dbHelper) - val viewModel = ViewModelProvider(this, ViewModelFactory(repository))[MainActivityViewModel::class.java] + val placeRepository = PlaceRepository(dbHelper) + val savedPlaceRepository = SavedPlaceRepository(dbHelper) + viewModel = + ViewModelProvider( + this, + ViewModelFactory(placeRepository, savedPlaceRepository) + )[MainActivityViewModel::class.java] val searchDeleteButton = findViewById(R.id.button_X) - searchDeleteButton.setOnClickListener{ + searchDeleteButton.setOnClickListener { inputSearchField.setText("") inputSearchField.clearFocus() } @@ -50,46 +59,65 @@ class MainActivity : AppCompatActivity() { Log.d("readData", "데이터 변경 감지") val place = viewModel.place Log.d("testt", "place") - place?.let{ + place?.let { recyclerView.layoutManager = LinearLayoutManager(this) - recyclerView.adapter = RecyclerViewAdapter(place,LayoutInflater.from(this), this) + recyclerView.adapter = PlaceViewAdapter(place, LayoutInflater.from(this), this) noResultText.visibility = View.INVISIBLE } - if(place.value?.isEmpty() == true) noResultText.visibility = View.VISIBLE + if (place.value?.isEmpty() == true) noResultText.visibility = View.VISIBLE }) - inputSearchField.addTextChangedListener(object : TextWatcher{ + inputSearchField.addTextChangedListener(object : TextWatcher { override fun beforeTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) { } override fun onTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) { } - override fun afterTextChanged(p0: Editable?) { - val text = inputSearchField.text.toString() + override fun afterTextChanged(searchText: Editable?) { + val text = searchText.toString() viewModel.getPlaceWithCategory(text) } }) } + + override fun savePlace(place: Place) { + Log.d("testt", "콜백함수 처리") + viewModel.savePlace(place) + } } -class RecyclerViewAdapter( - var placeList: LiveData>, - var inflater: LayoutInflater, - var context: Context -): RecyclerView.Adapter(){ +interface OnClickPlaceListener { + fun savePlace(place: Place) +} - inner class PlaceViewHolder(itemView : View) :RecyclerView.ViewHolder(itemView){ +class PlaceViewAdapter( + val placeList: LiveData>, + val inflater: LayoutInflater, + val listener: OnClickPlaceListener +) : RecyclerView.Adapter() { + + inner class PlaceViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { val name = itemView.findViewById(R.id.place_name) val location = itemView.findViewById(R.id.place_location) val category = itemView.findViewById(R.id.place_category) + + init { + itemView.setOnClickListener { + val position = absoluteAdapterPosition + Log.d("testt", "콜백함수 호출") + placeList.value?.get(position)?.let { listener.savePlace(it) } + } + } } override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): PlaceViewHolder { val view = inflater.inflate(R.layout.place_item, parent, false) Log.d("testt", "onCreateViewHolder") + // onCreateViewHolder에서 리스너? + return PlaceViewHolder(view) } @@ -102,4 +130,5 @@ class RecyclerViewAdapter( override fun getItemCount(): Int { return placeList.value?.size ?: 0 } -} \ No newline at end of file +} + diff --git a/app/src/main/java/campus/tech/kakao/map/viewmodel/MainActivityViewModel.kt b/app/src/main/java/campus/tech/kakao/map/viewmodel/MainActivityViewModel.kt index dfca5909..8a24590f 100644 --- a/app/src/main/java/campus/tech/kakao/map/viewmodel/MainActivityViewModel.kt +++ b/app/src/main/java/campus/tech/kakao/map/viewmodel/MainActivityViewModel.kt @@ -4,18 +4,36 @@ import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel import campus.tech.kakao.map.model.Place -import campus.tech.kakao.map.repository.Repository +import campus.tech.kakao.map.model.SavedPlace +import campus.tech.kakao.map.repository.PlaceRepository +import campus.tech.kakao.map.repository.SavedPlaceRepository import java.util.Locale.Category -class MainActivityViewModel (private val repository: Repository) : ViewModel() { - private var _place = MutableLiveData>() - val place : LiveData> get() = _place +class MainActivityViewModel( + private val placeRepository: PlaceRepository, + private val savedPlaceRepository: SavedPlaceRepository +) : ViewModel() { + private val _place = MutableLiveData>() + private val _savedPlace = MutableLiveData>() + val place: LiveData> get() = _place + val SavedPlace: LiveData> get() = _savedPlace - fun getPlace(){ - _place.postValue(repository.getAllPlace()) + fun getPlace() { + _place.postValue(placeRepository.getAllPlace()) } - fun getPlaceWithCategory(category: String){ - _place.postValue(repository.getPlaceWithCategory(category)) + fun getPlaceWithCategory(category: String) { + _place.postValue(placeRepository.getPlaceWithCategory(category)) } + + fun getSavedPlace() { + _savedPlace.postValue(savedPlaceRepository.getAllSavedPlace()) + } + + fun savePlace(place: Place) { + savedPlaceRepository.writePlace(place) + getSavedPlace() + } + + } \ No newline at end of file diff --git a/app/src/main/java/campus/tech/kakao/map/viewmodel/ViewModelFactory.kt b/app/src/main/java/campus/tech/kakao/map/viewmodel/ViewModelFactory.kt index c3f19288..22a2ff2d 100644 --- a/app/src/main/java/campus/tech/kakao/map/viewmodel/ViewModelFactory.kt +++ b/app/src/main/java/campus/tech/kakao/map/viewmodel/ViewModelFactory.kt @@ -2,12 +2,16 @@ package campus.tech.kakao.map.viewmodel import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModelProvider -import campus.tech.kakao.map.repository.Repository +import campus.tech.kakao.map.repository.PlaceRepository +import campus.tech.kakao.map.repository.SavedPlaceRepository -class ViewModelFactory(private val repository: Repository) : ViewModelProvider.Factory { +class ViewModelFactory( + private val placeRepository: PlaceRepository, + private val savedPlaceRepository: SavedPlaceRepository +) : ViewModelProvider.Factory { override fun create(modelClass: Class): T { - if(modelClass.isAssignableFrom(MainActivityViewModel::class.java)){ - return MainActivityViewModel(repository) as T + if (modelClass.isAssignableFrom(MainActivityViewModel::class.java)) { + return MainActivityViewModel(placeRepository, savedPlaceRepository) as T } throw IllegalArgumentException("unKnown ViewModel class") } diff --git a/app/src/main/res/layout/saved_place_item.xml b/app/src/main/res/layout/saved_place_item.xml new file mode 100644 index 00000000..59b85bf7 --- /dev/null +++ b/app/src/main/res/layout/saved_place_item.xml @@ -0,0 +1,29 @@ + + + + + + + + + \ No newline at end of file From 1f74a055d84c39455af4c894893a15cc7d8dfb54 Mon Sep 17 00:00:00 2001 From: fiveJinw Date: Fri, 5 Jul 2024 16:50:22 +0900 Subject: [PATCH 12/14] feat : add feature that display saved place list --- .../tech/kakao/map/view/MainActivity.kt | 55 ++++++++++++++++--- .../map/viewmodel/MainActivityViewModel.kt | 6 +- app/src/main/res/layout/activity_main.xml | 3 +- 3 files changed, 53 insertions(+), 11 deletions(-) diff --git a/app/src/main/java/campus/tech/kakao/map/view/MainActivity.kt b/app/src/main/java/campus/tech/kakao/map/view/MainActivity.kt index 93207a49..5003f14f 100644 --- a/app/src/main/java/campus/tech/kakao/map/view/MainActivity.kt +++ b/app/src/main/java/campus/tech/kakao/map/view/MainActivity.kt @@ -34,12 +34,15 @@ class MainActivity : AppCompatActivity(), OnClickPlaceListener { lateinit var noResultText: TextView lateinit var inputSearchField: EditText lateinit var viewModel : MainActivityViewModel + lateinit var savedPlaceRecyclerView : RecyclerView + lateinit var searchRecyclerView : RecyclerView override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) noResultText = findViewById(R.id.no_search_result) - val recyclerView = findViewById(R.id.search_result_recyclerView) + searchRecyclerView = findViewById(R.id.search_result_recyclerView) inputSearchField = findViewById(R.id.input_search_field) + savedPlaceRecyclerView = findViewById(R.id.saved_search_recyclerView) val dbHelper = PlaceDBHelper(this) val placeRepository = PlaceRepository(dbHelper) val savedPlaceRepository = SavedPlaceRepository(dbHelper) @@ -53,20 +56,33 @@ class MainActivity : AppCompatActivity(), OnClickPlaceListener { inputSearchField.setText("") inputSearchField.clearFocus() } + val searchRecyclerViewAdapter = PlaceViewAdapter(viewModel.place, LayoutInflater.from(this), this) + val savedPlaceRecyclerViewAdapter = SavedPlaceViewAdapter(viewModel.savedPlace, LayoutInflater.from(this)) + searchRecyclerView.layoutManager = LinearLayoutManager(this) + searchRecyclerView.adapter = searchRecyclerViewAdapter + savedPlaceRecyclerView.layoutManager = LinearLayoutManager(this, RecyclerView.HORIZONTAL, false) + savedPlaceRecyclerView.adapter =savedPlaceRecyclerViewAdapter + Log.d("testt", viewModel.place.toString()) - viewModel.place.observe(this, Observer { newData -> - Log.d("readData", "데이터 변경 감지") + viewModel.place.observe(this, Observer { + Log.d("readData", "검색창 결과 변경 감지") val place = viewModel.place Log.d("testt", "place") place?.let { - recyclerView.layoutManager = LinearLayoutManager(this) - recyclerView.adapter = PlaceViewAdapter(place, LayoutInflater.from(this), this) + searchRecyclerViewAdapter.notifyDataSetChanged() noResultText.visibility = View.INVISIBLE } if (place.value?.isEmpty() == true) noResultText.visibility = View.VISIBLE }) + viewModel.savedPlace.observe(this, Observer { + Log.d("readData", "저장된 장소들 변경 감지") + val savedPlace = viewModel.savedPlace + savedPlaceRecyclerViewAdapter.notifyDataSetChanged() + if (savedPlace.value?.isEmpty() == true) savedPlaceRecyclerView.visibility = View.GONE + }) + inputSearchField.addTextChangedListener(object : TextWatcher { override fun beforeTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) { } @@ -115,9 +131,7 @@ class PlaceViewAdapter( override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): PlaceViewHolder { val view = inflater.inflate(R.layout.place_item, parent, false) - Log.d("testt", "onCreateViewHolder") - // onCreateViewHolder에서 리스너? - + Log.d("testt", "검색 결과 뷰 생성") return PlaceViewHolder(view) } @@ -132,3 +146,28 @@ class PlaceViewAdapter( } } +class SavedPlaceViewAdapter( + val savedPlaceList: LiveData>, + val inflater: LayoutInflater +): RecyclerView.Adapter(){ + + inner class SavedPlaceViewHolder(itemView : View) :RecyclerView.ViewHolder(itemView){ + val name = itemView.findViewById(R.id.saved_place_name) + val deleteButton = itemView.findViewById(R.id.button_saved_delete) + + } + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): SavedPlaceViewHolder { + val view = inflater.inflate(R.layout.saved_place_item, parent, false) + Log.d("testt", "저장된 장소를 띄우는 뷰 홀더 생성") + return SavedPlaceViewHolder(view) + } + + override fun onBindViewHolder(holder: SavedPlaceViewHolder, position: Int) { + holder.name.text = savedPlaceList.value?.get(position)?.name ?: "" + } + + override fun getItemCount(): Int { + return savedPlaceList.value?.size ?: 0 + } +} diff --git a/app/src/main/java/campus/tech/kakao/map/viewmodel/MainActivityViewModel.kt b/app/src/main/java/campus/tech/kakao/map/viewmodel/MainActivityViewModel.kt index 8a24590f..ed91e89b 100644 --- a/app/src/main/java/campus/tech/kakao/map/viewmodel/MainActivityViewModel.kt +++ b/app/src/main/java/campus/tech/kakao/map/viewmodel/MainActivityViewModel.kt @@ -16,8 +16,10 @@ class MainActivityViewModel( private val _place = MutableLiveData>() private val _savedPlace = MutableLiveData>() val place: LiveData> get() = _place - val SavedPlace: LiveData> get() = _savedPlace - + val savedPlace: LiveData> get() = _savedPlace + init{ + getSavedPlace() + } fun getPlace() { _place.postValue(placeRepository.getAllPlace()) } diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index 56789b64..9710b75c 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -39,13 +39,14 @@ app:layout_constraintBottom_toTopOf="@id/search_result_recyclerView" app:layout_constraintStart_toStartOf="parent" app:layout_constraintEnd_toEndOf="parent" - android:visibility="gone" + android:layout_marginTop="10dp" /> Date: Fri, 5 Jul 2024 17:03:51 +0900 Subject: [PATCH 13/14] feat : Add feature that delete saved place --- .../map/repository/SavedPlaceRepository.kt | 4 +++ .../tech/kakao/map/view/MainActivity.kt | 25 ++++++++++++++++--- .../map/viewmodel/MainActivityViewModel.kt | 5 ++++ 3 files changed, 30 insertions(+), 4 deletions(-) diff --git a/app/src/main/java/campus/tech/kakao/map/repository/SavedPlaceRepository.kt b/app/src/main/java/campus/tech/kakao/map/repository/SavedPlaceRepository.kt index 8ce201b4..c54cb81a 100644 --- a/app/src/main/java/campus/tech/kakao/map/repository/SavedPlaceRepository.kt +++ b/app/src/main/java/campus/tech/kakao/map/repository/SavedPlaceRepository.kt @@ -36,4 +36,8 @@ class SavedPlaceRepository (val dbHelper: PlaceDBHelper){ dbHelper.insertSavedPlaceData(place.name) } } + + fun deleteSavedPlace(savedPlace: SavedPlace){ + dbHelper.deleteSavedPlace(savedPlace.name) + } } \ No newline at end of file diff --git a/app/src/main/java/campus/tech/kakao/map/view/MainActivity.kt b/app/src/main/java/campus/tech/kakao/map/view/MainActivity.kt index 5003f14f..d1f3f5a9 100644 --- a/app/src/main/java/campus/tech/kakao/map/view/MainActivity.kt +++ b/app/src/main/java/campus/tech/kakao/map/view/MainActivity.kt @@ -30,7 +30,7 @@ import campus.tech.kakao.map.viewmodel.MainActivityViewModel import campus.tech.kakao.map.viewmodel.ViewModelFactory -class MainActivity : AppCompatActivity(), OnClickPlaceListener { +class MainActivity : AppCompatActivity(), OnClickPlaceListener, OnClickSavedPlaceListener { lateinit var noResultText: TextView lateinit var inputSearchField: EditText lateinit var viewModel : MainActivityViewModel @@ -57,11 +57,11 @@ class MainActivity : AppCompatActivity(), OnClickPlaceListener { inputSearchField.clearFocus() } val searchRecyclerViewAdapter = PlaceViewAdapter(viewModel.place, LayoutInflater.from(this), this) - val savedPlaceRecyclerViewAdapter = SavedPlaceViewAdapter(viewModel.savedPlace, LayoutInflater.from(this)) + val savedPlaceRecyclerViewAdapter = SavedPlaceViewAdapter(viewModel.savedPlace, LayoutInflater.from(this), this) searchRecyclerView.layoutManager = LinearLayoutManager(this) searchRecyclerView.adapter = searchRecyclerViewAdapter savedPlaceRecyclerView.layoutManager = LinearLayoutManager(this, RecyclerView.HORIZONTAL, false) - savedPlaceRecyclerView.adapter =savedPlaceRecyclerViewAdapter + savedPlaceRecyclerView.adapter = savedPlaceRecyclerViewAdapter Log.d("testt", viewModel.place.toString()) @@ -99,6 +99,11 @@ class MainActivity : AppCompatActivity(), OnClickPlaceListener { } + override fun deleteSavedPlace(savedPlace: SavedPlace) { + Log.d("testt", "삭제 콜백함수 처리") + viewModel.deleteSavedPlace(savedPlace) + } + override fun savePlace(place: Place) { Log.d("testt", "콜백함수 처리") viewModel.savePlace(place) @@ -109,6 +114,10 @@ interface OnClickPlaceListener { fun savePlace(place: Place) } +interface OnClickSavedPlaceListener { + fun deleteSavedPlace(savedPlace: SavedPlace) +} + class PlaceViewAdapter( val placeList: LiveData>, val inflater: LayoutInflater, @@ -148,12 +157,20 @@ class PlaceViewAdapter( class SavedPlaceViewAdapter( val savedPlaceList: LiveData>, - val inflater: LayoutInflater + val inflater: LayoutInflater, + val listener : OnClickSavedPlaceListener ): RecyclerView.Adapter(){ inner class SavedPlaceViewHolder(itemView : View) :RecyclerView.ViewHolder(itemView){ val name = itemView.findViewById(R.id.saved_place_name) val deleteButton = itemView.findViewById(R.id.button_saved_delete) + init { + deleteButton.setOnClickListener{ + val position = absoluteAdapterPosition + Log.d("testt", "삭제 콜백함수 호출") + savedPlaceList.value?.get(position)?.let { listener.deleteSavedPlace(it) } + } + } } diff --git a/app/src/main/java/campus/tech/kakao/map/viewmodel/MainActivityViewModel.kt b/app/src/main/java/campus/tech/kakao/map/viewmodel/MainActivityViewModel.kt index ed91e89b..cfaaf5c8 100644 --- a/app/src/main/java/campus/tech/kakao/map/viewmodel/MainActivityViewModel.kt +++ b/app/src/main/java/campus/tech/kakao/map/viewmodel/MainActivityViewModel.kt @@ -37,5 +37,10 @@ class MainActivityViewModel( getSavedPlace() } + fun deleteSavedPlace(savedPlace: SavedPlace){ + savedPlaceRepository.deleteSavedPlace(savedPlace) + getSavedPlace() + } + } \ No newline at end of file From de3eb6d857c5f37b286ff73025895ea7b85ed876 Mon Sep 17 00:00:00 2001 From: fiveJinw Date: Fri, 5 Jul 2024 17:32:19 +0900 Subject: [PATCH 14/14] refactor : refactor MainActivity code --- README.md | 10 +- .../kakao/map/adapter/PlaceViewAdapter.kt | 49 +++++ .../map/adapter/SavedPlaceViewAdapter.kt | 48 +++++ .../tech/kakao/map/view/ClickListener.kt | 12 ++ .../tech/kakao/map/view/MainActivity.kt | 187 +++++++----------- 5 files changed, 185 insertions(+), 121 deletions(-) create mode 100644 app/src/main/java/campus/tech/kakao/map/adapter/PlaceViewAdapter.kt create mode 100644 app/src/main/java/campus/tech/kakao/map/adapter/SavedPlaceViewAdapter.kt create mode 100644 app/src/main/java/campus/tech/kakao/map/view/ClickListener.kt diff --git a/README.md b/README.md index 6de92dae..3eb34c00 100644 --- a/README.md +++ b/README.md @@ -14,10 +14,10 @@ **검색 관련 기능** -- [ ] 검색어를 입력하면 검색 결과 목록을 스크롤이 가능하도록 띄우는 기능 -- [ ] X를 누르면 입력한 검색어를 삭제하는 기능 +- [x] 검색어를 입력하면 검색 결과 목록을 스크롤이 가능하도록 띄우는 기능 +- [x] X를 누르면 입력한 검색어를 삭제하는 기능 **저장 관련 기능** -- [ ] 검색 결과 목록중 하나를 클릭하면 저장하는 기능 -- [ ] 저장된 목록을 검색창 밑에서 가로 스크롤이 가능하도록 띄우는 기능 -- [ ] 저장된 목록중 X를 누르면 저장된 목록을 삭제하는 기능 +- [x] 검색 결과 목록중 하나를 클릭하면 저장하는 기능 +- [x] 저장된 목록을 검색창 밑에서 가로 스크롤이 가능하도록 띄우는 기능 +- [x] 저장된 목록중 X를 누르면 저장된 목록을 삭제하는 기능 diff --git a/app/src/main/java/campus/tech/kakao/map/adapter/PlaceViewAdapter.kt b/app/src/main/java/campus/tech/kakao/map/adapter/PlaceViewAdapter.kt new file mode 100644 index 00000000..d1fc3191 --- /dev/null +++ b/app/src/main/java/campus/tech/kakao/map/adapter/PlaceViewAdapter.kt @@ -0,0 +1,49 @@ +package campus.tech.kakao.map.adapter + +import android.util.Log +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.TextView +import androidx.lifecycle.LiveData +import androidx.recyclerview.widget.RecyclerView +import campus.tech.kakao.map.view.OnClickPlaceListener +import campus.tech.kakao.map.R +import campus.tech.kakao.map.model.Place + +class PlaceViewAdapter( + val placeList: LiveData>, + val inflater: LayoutInflater, + val listener: OnClickPlaceListener +) : RecyclerView.Adapter() { + + inner class PlaceViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { + val name = itemView.findViewById(R.id.place_name) + val location = itemView.findViewById(R.id.place_location) + val category = itemView.findViewById(R.id.place_category) + + init { + itemView.setOnClickListener { + val position = absoluteAdapterPosition + Log.d("testt", "콜백함수 호출") + placeList.value?.get(position)?.let { listener.savePlace(it) } + } + } + } + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): PlaceViewHolder { + val view = inflater.inflate(R.layout.place_item, parent, false) + Log.d("testt", "검색 결과 뷰 생성") + return PlaceViewHolder(view) + } + + override fun onBindViewHolder(holder: PlaceViewHolder, position: Int) { + holder.name.text = placeList.value?.get(position)?.name ?: "" + holder.location.text = placeList.value?.get(position)?.location ?: "" + holder.category.text = placeList.value?.get(position)?.category ?: "" + } + + override fun getItemCount(): Int { + return placeList.value?.size ?: 0 + } +} \ No newline at end of file diff --git a/app/src/main/java/campus/tech/kakao/map/adapter/SavedPlaceViewAdapter.kt b/app/src/main/java/campus/tech/kakao/map/adapter/SavedPlaceViewAdapter.kt new file mode 100644 index 00000000..8ae34ed1 --- /dev/null +++ b/app/src/main/java/campus/tech/kakao/map/adapter/SavedPlaceViewAdapter.kt @@ -0,0 +1,48 @@ +package campus.tech.kakao.map.adapter + +import android.util.Log +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.ImageView +import android.widget.TextView +import androidx.lifecycle.LiveData +import androidx.recyclerview.widget.RecyclerView +import campus.tech.kakao.map.view.OnClickSavedPlaceListener +import campus.tech.kakao.map.R +import campus.tech.kakao.map.model.SavedPlace + +class SavedPlaceViewAdapter( + val savedPlaceList: LiveData>, + val inflater: LayoutInflater, + val listener: OnClickSavedPlaceListener +) : RecyclerView.Adapter() { + + inner class SavedPlaceViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { + val name = itemView.findViewById(R.id.saved_place_name) + val deleteButton = itemView.findViewById(R.id.button_saved_delete) + + init { + deleteButton.setOnClickListener { + val position = absoluteAdapterPosition + Log.d("testt", "삭제 콜백함수 호출") + savedPlaceList.value?.get(position)?.let { listener.deleteSavedPlace(it, position) } + } + } + + } + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): SavedPlaceViewHolder { + val view = inflater.inflate(R.layout.saved_place_item, parent, false) + Log.d("testt", "저장된 장소를 띄우는 뷰 홀더 생성") + return SavedPlaceViewHolder(view) + } + + override fun onBindViewHolder(holder: SavedPlaceViewHolder, position: Int) { + holder.name.text = savedPlaceList.value?.get(position)?.name ?: "" + } + + override fun getItemCount(): Int { + return savedPlaceList.value?.size ?: 0 + } +} diff --git a/app/src/main/java/campus/tech/kakao/map/view/ClickListener.kt b/app/src/main/java/campus/tech/kakao/map/view/ClickListener.kt new file mode 100644 index 00000000..b42e2ae9 --- /dev/null +++ b/app/src/main/java/campus/tech/kakao/map/view/ClickListener.kt @@ -0,0 +1,12 @@ +package campus.tech.kakao.map.view + +import campus.tech.kakao.map.model.Place +import campus.tech.kakao.map.model.SavedPlace + +interface OnClickPlaceListener { + fun savePlace(place: Place) +} + +interface OnClickSavedPlaceListener { + fun deleteSavedPlace(savedPlace: SavedPlace, position: Int) +} \ No newline at end of file diff --git a/app/src/main/java/campus/tech/kakao/map/view/MainActivity.kt b/app/src/main/java/campus/tech/kakao/map/view/MainActivity.kt index d1f3f5a9..ba3e60ba 100644 --- a/app/src/main/java/campus/tech/kakao/map/view/MainActivity.kt +++ b/app/src/main/java/campus/tech/kakao/map/view/MainActivity.kt @@ -1,26 +1,22 @@ package campus.tech.kakao.map.view -import android.content.Context import android.os.Bundle import android.text.Editable import android.text.TextWatcher import android.util.Log import android.view.LayoutInflater import android.view.View -import android.view.ViewGroup import android.widget.EditText import android.widget.ImageView import android.widget.TextView import androidx.appcompat.app.AppCompatActivity -import androidx.core.widget.addTextChangedListener -import androidx.lifecycle.LiveData import androidx.lifecycle.Observer import androidx.lifecycle.ViewModelProvider -import androidx.lifecycle.viewmodel.viewModelFactory import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView -import androidx.recyclerview.widget.RecyclerView.OnChildAttachStateChangeListener import campus.tech.kakao.map.R +import campus.tech.kakao.map.adapter.PlaceViewAdapter +import campus.tech.kakao.map.adapter.SavedPlaceViewAdapter import campus.tech.kakao.map.db.PlaceDBHelper import campus.tech.kakao.map.model.Place import campus.tech.kakao.map.model.SavedPlace @@ -33,47 +29,31 @@ import campus.tech.kakao.map.viewmodel.ViewModelFactory class MainActivity : AppCompatActivity(), OnClickPlaceListener, OnClickSavedPlaceListener { lateinit var noResultText: TextView lateinit var inputSearchField: EditText - lateinit var viewModel : MainActivityViewModel - lateinit var savedPlaceRecyclerView : RecyclerView - lateinit var searchRecyclerView : RecyclerView + lateinit var viewModel: MainActivityViewModel + lateinit var savedPlaceRecyclerView: RecyclerView + lateinit var searchRecyclerView: RecyclerView + lateinit var dbHelper: PlaceDBHelper + lateinit var placeRepository: PlaceRepository + lateinit var savedPlaceRepository: SavedPlaceRepository + lateinit var searchDeleteButton: ImageView + lateinit var savedPlaceRecyclerViewAdapter: SavedPlaceViewAdapter + lateinit var searchRecyclerViewAdapter: PlaceViewAdapter + override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) - noResultText = findViewById(R.id.no_search_result) - searchRecyclerView = findViewById(R.id.search_result_recyclerView) - inputSearchField = findViewById(R.id.input_search_field) - savedPlaceRecyclerView = findViewById(R.id.saved_search_recyclerView) - val dbHelper = PlaceDBHelper(this) - val placeRepository = PlaceRepository(dbHelper) - val savedPlaceRepository = SavedPlaceRepository(dbHelper) - viewModel = - ViewModelProvider( - this, - ViewModelFactory(placeRepository, savedPlaceRepository) - )[MainActivityViewModel::class.java] - val searchDeleteButton = findViewById(R.id.button_X) - searchDeleteButton.setOnClickListener { - inputSearchField.setText("") - inputSearchField.clearFocus() - } - val searchRecyclerViewAdapter = PlaceViewAdapter(viewModel.place, LayoutInflater.from(this), this) - val savedPlaceRecyclerViewAdapter = SavedPlaceViewAdapter(viewModel.savedPlace, LayoutInflater.from(this), this) - searchRecyclerView.layoutManager = LinearLayoutManager(this) - searchRecyclerView.adapter = searchRecyclerViewAdapter - savedPlaceRecyclerView.layoutManager = LinearLayoutManager(this, RecyclerView.HORIZONTAL, false) - savedPlaceRecyclerView.adapter = savedPlaceRecyclerViewAdapter - + initVar() + initListeners() + initRecyclerViews() Log.d("testt", viewModel.place.toString()) + viewModel.place.observe(this, Observer { Log.d("readData", "검색창 결과 변경 감지") val place = viewModel.place - Log.d("testt", "place") - place?.let { - searchRecyclerViewAdapter.notifyDataSetChanged() - noResultText.visibility = View.INVISIBLE - } + searchRecyclerViewAdapter.notifyDataSetChanged() if (place.value?.isEmpty() == true) noResultText.visibility = View.VISIBLE + else noResultText.visibility = View.INVISIBLE }) viewModel.savedPlace.observe(this, Observer { @@ -81,25 +61,11 @@ class MainActivity : AppCompatActivity(), OnClickPlaceListener, OnClickSavedPlac val savedPlace = viewModel.savedPlace savedPlaceRecyclerViewAdapter.notifyDataSetChanged() if (savedPlace.value?.isEmpty() == true) savedPlaceRecyclerView.visibility = View.GONE + else savedPlaceRecyclerView.visibility = View.VISIBLE }) - - inputSearchField.addTextChangedListener(object : TextWatcher { - override fun beforeTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) { - } - - override fun onTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) { - } - - override fun afterTextChanged(searchText: Editable?) { - val text = searchText.toString() - viewModel.getPlaceWithCategory(text) - } - }) - - } - override fun deleteSavedPlace(savedPlace: SavedPlace) { + override fun deleteSavedPlace(savedPlace: SavedPlace, position: Int) { Log.d("testt", "삭제 콜백함수 처리") viewModel.deleteSavedPlace(savedPlace) } @@ -108,83 +74,72 @@ class MainActivity : AppCompatActivity(), OnClickPlaceListener, OnClickSavedPlac Log.d("testt", "콜백함수 처리") viewModel.savePlace(place) } -} - -interface OnClickPlaceListener { - fun savePlace(place: Place) -} -interface OnClickSavedPlaceListener { - fun deleteSavedPlace(savedPlace: SavedPlace) -} - -class PlaceViewAdapter( - val placeList: LiveData>, - val inflater: LayoutInflater, - val listener: OnClickPlaceListener -) : RecyclerView.Adapter() { - - inner class PlaceViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { - val name = itemView.findViewById(R.id.place_name) - val location = itemView.findViewById(R.id.place_location) - val category = itemView.findViewById(R.id.place_category) - - init { - itemView.setOnClickListener { - val position = absoluteAdapterPosition - Log.d("testt", "콜백함수 호출") - placeList.value?.get(position)?.let { listener.savePlace(it) } - } - } + fun initVar() { + noResultText = findViewById(R.id.no_search_result) + searchRecyclerView = findViewById(R.id.search_result_recyclerView) + inputSearchField = findViewById(R.id.input_search_field) + savedPlaceRecyclerView = findViewById(R.id.saved_search_recyclerView) + dbHelper = PlaceDBHelper(this) + placeRepository = PlaceRepository(dbHelper) + savedPlaceRepository = SavedPlaceRepository(dbHelper) + searchDeleteButton = findViewById(R.id.button_X) + viewModel = + ViewModelProvider( + this, + ViewModelFactory(placeRepository, savedPlaceRepository) + )[MainActivityViewModel::class.java] } - override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): PlaceViewHolder { - val view = inflater.inflate(R.layout.place_item, parent, false) - Log.d("testt", "검색 결과 뷰 생성") - return PlaceViewHolder(view) + fun initListeners() { + initDeleteButtonListener() + initInputFieldListener() } - override fun onBindViewHolder(holder: PlaceViewHolder, position: Int) { - holder.name.text = placeList.value?.get(position)?.name ?: "" - holder.location.text = placeList.value?.get(position)?.location ?: "" - holder.category.text = placeList.value?.get(position)?.category ?: "" + fun initDeleteButtonListener(){ + searchDeleteButton.setOnClickListener { + inputSearchField.setText("") + inputSearchField.clearFocus() + } } - override fun getItemCount(): Int { - return placeList.value?.size ?: 0 - } -} + fun initInputFieldListener(){ + inputSearchField.addTextChangedListener(object : TextWatcher { + override fun beforeTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) { + } -class SavedPlaceViewAdapter( - val savedPlaceList: LiveData>, - val inflater: LayoutInflater, - val listener : OnClickSavedPlaceListener -): RecyclerView.Adapter(){ - - inner class SavedPlaceViewHolder(itemView : View) :RecyclerView.ViewHolder(itemView){ - val name = itemView.findViewById(R.id.saved_place_name) - val deleteButton = itemView.findViewById(R.id.button_saved_delete) - init { - deleteButton.setOnClickListener{ - val position = absoluteAdapterPosition - Log.d("testt", "삭제 콜백함수 호출") - savedPlaceList.value?.get(position)?.let { listener.deleteSavedPlace(it) } + override fun onTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) { } - } + override fun afterTextChanged(searchText: Editable?) { + val text = searchText.toString() + // 검색어를 입력할 때마다 place의 값이 바뀌어 notify가 계속 호출되는 문제? + viewModel.getPlaceWithCategory(text) + } + }) } - override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): SavedPlaceViewHolder { - val view = inflater.inflate(R.layout.saved_place_item, parent, false) - Log.d("testt", "저장된 장소를 띄우는 뷰 홀더 생성") - return SavedPlaceViewHolder(view) + fun initRecyclerViews() { + initSearchRecyclerView() + initSavedPlaceRecyclerView() } - override fun onBindViewHolder(holder: SavedPlaceViewHolder, position: Int) { - holder.name.text = savedPlaceList.value?.get(position)?.name ?: "" + fun initSearchRecyclerView() { + searchRecyclerViewAdapter = PlaceViewAdapter(viewModel.place, LayoutInflater.from(this), this) + searchRecyclerView.layoutManager = LinearLayoutManager(this) + searchRecyclerView.adapter = searchRecyclerViewAdapter } - override fun getItemCount(): Int { - return savedPlaceList.value?.size ?: 0 + fun initSavedPlaceRecyclerView() { + savedPlaceRecyclerViewAdapter = + SavedPlaceViewAdapter(viewModel.savedPlace, LayoutInflater.from(this), this) + savedPlaceRecyclerView.layoutManager = + LinearLayoutManager(this, RecyclerView.HORIZONTAL, false) + savedPlaceRecyclerView.adapter = savedPlaceRecyclerViewAdapter } } + + + + +