-
Notifications
You must be signed in to change notification settings - Fork 33
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
전남대 Android_오진우_2주차 과제_Step2 #57
base: fivejinw
Are you sure you want to change the base?
Changes from all commits
9fb7585
3228d66
9249097
8ee5a1e
1936a12
576db54
25408b8
d641354
c3722dd
988a64f
47ccbc4
1f74a05
808a57f
de3eb6d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,23 @@ | ||
# android-map-keyword | ||
# 2주차 - android-map-keyword | ||
## step1 구현할 기능 목록 | ||
|
||
**UI 관련 기능** | ||
- [x] 검색어를 입력할 수 있는 칸 구현 | ||
- [x] 검색 결과를 표시할 수 있는 칸 구현 | ||
- [x] 저장된 검색 결과를 표시할 수 있는 칸 구현 | ||
|
||
**DB 관련 기능** | ||
- [x] 장소의 이름, 장소의 위치. 장소 카테고리를 저장할 수 있는 데이터베이스 구현 | ||
|
||
--------------------------- | ||
## step2 구현할 기능 목록 | ||
|
||
|
||
**검색 관련 기능** | ||
- [x] 검색어를 입력하면 검색 결과 목록을 스크롤이 가능하도록 띄우는 기능 | ||
- [x] X를 누르면 입력한 검색어를 삭제하는 기능 | ||
|
||
**저장 관련 기능** | ||
- [x] 검색 결과 목록중 하나를 클릭하면 저장하는 기능 | ||
- [x] 저장된 목록을 검색창 밑에서 가로 스크롤이 가능하도록 띄우는 기능 | ||
- [x] 저장된 목록중 X를 누르면 저장된 목록을 삭제하는 기능 |
This file was deleted.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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<MutableList<Place>>, | ||
val inflater: LayoutInflater, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. inflater 를 굳이 parameter 를 통해서 받을 필요는 없습니다. onCreateViewHolder 의 parent: RecyclerView 의 context 를 사용하시면 됩니다 :)
|
||
val listener: OnClickPlaceListener | ||
) : RecyclerView.Adapter<PlaceViewAdapter.PlaceViewHolder>() { | ||
|
||
inner class PlaceViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 여기도 또한 inner class 가 아닌 형태로 처리하는 것으로 고려해주시면 좋을 것 같아요! ViewHolder 에서 adapter 를 접근하는 것이 올바른 형태는 아니에요! |
||
val name = itemView.findViewById<TextView>(R.id.place_name) | ||
val location = itemView.findViewById<TextView>(R.id.place_location) | ||
val category = itemView.findViewById<TextView>(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 | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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<MutableList<SavedPlace>>, | ||
val inflater: LayoutInflater, | ||
val listener: OnClickSavedPlaceListener | ||
) : RecyclerView.Adapter<SavedPlaceViewAdapter.SavedPlaceViewHolder>() { | ||
|
||
inner class SavedPlaceViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { | ||
val name = itemView.findViewById<TextView>(R.id.saved_place_name) | ||
val deleteButton = itemView.findViewById<ImageView>(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 | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
package campus.tech.kakao.map.db | ||
|
||
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" | ||
} | ||
|
||
object SavedPlaceEntry : BaseColumns{ | ||
const val TABLE_NAME = "SAVED_PLACE" | ||
const val COLUMN_NAME = "SAVED_NAME" | ||
} | ||
} | ||
Comment on lines
+5
to
+17
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 👍 |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,92 @@ | ||
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, 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.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) { | ||
insertPlaceData(name + i, location + i, category) | ||
} | ||
readPlaceData() | ||
} | ||
|
||
fun insertPlaceData(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 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 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.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)) | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
package campus.tech.kakao.map.model | ||
|
||
data class Place( | ||
val name : String, | ||
val location : String, | ||
val category : String | ||
) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
package campus.tech.kakao.map.model | ||
|
||
data class SavedPlace( | ||
val name: String | ||
) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
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 PlaceRepository (val dbHelper: PlaceDBHelper){ | ||
fun getAllPlace() : MutableList<Place>{ | ||
val cursor = dbHelper.readPlaceData() | ||
val placeList = mutableListOf<Place>() | ||
|
||
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 | ||
} | ||
|
||
fun writePlace(place: Place){ | ||
dbHelper.insertPlaceData(place.name, place.location, place.category) | ||
} | ||
|
||
fun getPlaceWithCategory(category : String): MutableList<Place>{ | ||
val cursor = dbHelper.readPlaceDataWithSamedCategory(category) | ||
val placeList = mutableListOf<Place>() | ||
|
||
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 | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
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<SavedPlace>{ | ||
val cursor = dbHelper.readSavedPlaceData() | ||
val placeList = mutableListOf<SavedPlace>() | ||
|
||
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) | ||
} | ||
} | ||
|
||
fun deleteSavedPlace(savedPlace: SavedPlace){ | ||
dbHelper.deleteSavedPlace(savedPlace.name) | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
PlaceViewAdapter 에서 LiveData 를 파라미터로 받고 있는데, 그런 사용은 지양해주시면 좋을 것 같아요! adapter 내에서 observe 하는 것도 없고, adapter 에서 필요한 것은 List 일 뿐이니까요!