이전 아래 글에서 SQLite Open Helper클래스를 상속받아 SQLite를 사용하기 위한 Helper클래스를 만들어 보았습니다.
2020/10/09 - [Mobile/Kotlin] - [kotlin] SQLite - SQLite Open Helper 구현하기
이번에는 위에서 만든 이 Helper클래스를 이용해 간단한 전화번호부 앱을 만들면서 직접 연결하고 사용하는 방법을 알가 보고자 합니다.
우선 Activity Main에서 화면을 다음과 같이 디자인합니다.
가장 상단에는 RecyclerView를 배치하고 그 아래 2개의 Plain Text 그리고 Button하나를 순서대로 배치합니다. 예제에서 RecyclerView의 ID는 rccList, Plain Text는 txtName과 txtPhone, 그리고 Button은 btnSave로 ID를 지정하였습니다.
다음 단계로 rccList에서 Item으로 표시될 Layout파일을 생성합니다. app -> rec -> layout에서 마우스 오른쪽 버튼을 눌러 New -> Layout Resource File을 선택하세요.
File Name을 phone_book_item으로 입력하고 OK를 눌러줍니다.
phone_book_item은 다음과 같이 디자인합니다.
우선 상위의 ConstraintLayout은 세로 크기를 50dp로 고정하였습니다. 그다음 내부에 3개의 TextView를 배치하고 번호를 표시할 TextView는 tvSeq, 이름을 표시할 TextView은 tvName 그리고 전화번호는 tvPhone로 각각 ID를 지정하였습니다.
그다음 이전 포스팅에서 생성한 PhoneBook클래스를 데이터로 하는 Adapter클래스를 생성합니다. app -> java -> [패키 지명]에서 마우스 오른쪽 버튼을 눌러 New -> Kotlin File/Class를 선택하세요.
이어지는 화면에서 Class를 선택하고 이름에 RecyclerAdapter를 입력해 파일을 생성합니다.
파일이 생성되면 RecyclerAdapter 클래스 아래 Holder클래스를 생성합니다. phoneBook에서 seq, name, phone값을 가져와 위에서 추가한 item의 textView에 표시되도록 하기 위한 것입니다.
class Holder(itemView: View): RecyclerView.ViewHolder(itemView) {
fun getPhoneBook(phoneBook: PhoneBook) {
itemView.tvSeq.text = "${phoneBook.seq.toString()}"
itemView.tvName.text = "${phoneBook.name}"
itemView.tvPhone.text = "${phoneBook.phone}"
}
}
Holder를 만들었으면 위에서 생성된 RecyclerAdapter에 RecyclerView.Adapter<Holder>()를 상속받도록 하고
class RecyclerAdapter: RecyclerView.Adapter<Holder>() {
}
RecyclerAdapter 블록안에서 Ctrl + I키를 눌러 모든 메서드를 생성하도록 합니다.
onCreateViewHolder에서는 앞에서 만들어둔 phone_book_item을 Holder로 묶어 반환하도록 합니다.
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): Holder {
val view = LayoutInflater.from(parent.context).inflate(R.layout.phone_book_item, parent, false)
return Holder(view)
}
그리고 클래스 안에서 PhoneBook타입의 data를 생성해 onBindViewHolder에서 특정 위치의 전화번호 item을 가져와 Holder에 표시할 수 있도록 합니다.
var pbList = mutableListOf<PhoneBook>()
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): Holder {
val view = LayoutInflater.from(parent.context).inflate(R.layout.phone_book_item, parent, false)
return Holder(view)
}
override fun onBindViewHolder(holder: Holder, position: Int) {
val pb = pbList.get(position)
holder.getPhoneBook(pb)
}
마지막으로 getItemCount() 에서는 전체 데이터의 수를 반환하도록 합니다.
class RecyclerAdapter: RecyclerView.Adapter<Holder>() {
var pbList = mutableListOf<PhoneBook>()
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): Holder {
val view = LayoutInflater.from(parent.context).inflate(R.layout.phone_book_item, parent, false)
return Holder(view)
}
override fun onBindViewHolder(holder: Holder, position: Int) {
val pb = pbList.get(position)
holder.getPhoneBook(pb)
}
override fun getItemCount(): Int {
return pbList.size
}
}
이제 MainActivity로 돌아와 이전에 만들어둔 SQLiteHelper를 onCreate() 메서드 바로 위에 생성합니다.
val sqlite = SQLiteHelper(this, "phonebook", 1)
그리고 다시 onCreate()안에서 RecyclerAdapter를 생성하고 adapter에서 현재의 모든 전화번호부 목록을 가져올 수 있도록 합니다.
val adapter = RecyclerAdapter()
adapter.pbList.addAll(sqlite.getPhoneBook())
이렇게 생성된 adapter를 activity_main에 만들어둔 rcclist의 adapter와 연결합니다.
rccList.adapter = adapter
rccList.layoutManager = LinearLayoutManager(this)
기본적인 연결은 끝났고 이제 버튼을 눌렀을 때 전화번호를 저장하는 기능을 구현합니다. activity_main에서 저장버튼을 누르는 경우 SQLiteHelper클래스의 addPhoneBook() 메서드를 호출하여 입력한 내용으로 전화번호를 저장하도록 합니다.
그리고 저장직후에는 기존의 데이터는 제거하고 새롭게 추가한 데이터와 함께 전화번호부 목록을 새로 불러와 RecyclerView에 표시하도록 합니다.
btnSave.setOnClickListener {
val pbItem = PhoneBook(null, txtName.text.toString(), txtPhone.text.toString())
sqlite.addPhoneBook(pbItem)
adapter.pbList.clear()
adapter.pbList.addAll(sqlite.getPhoneBook())
adapter.notifyDataSetChanged()
}
이제 전화번호를 잘못저장했을 경우를 대비해 삭제하는 기능을 추가해 보도록 하겠습니다. 다음과 같이 phone_book_item에서 '삭제'버튼을 추가합니다. 버튼의 ID는 btnDelete로 하였습니다.
추가한 삭제버튼을 통해 실제 데이터를 삭제하려면 SQLiteHelper 쪽으로 접근해야 하는데 버튼이 activity_main에 있는 게 아니라 phone_booK_item 쪽에 있으므로 SQLiteHepler를 접근 가능한 RecyclerAdapter.kt 쪽으로 끌어와야 합니다. 이를 위해 RecyclerAdapter에서 다음과 같이 SQLiteHepler를 가질 수 있는 변수를 생성하고
var sqlite: SQLiteHelper? = null
MainActivity에서 SQLiteHelper를 대입하도록 합니다.
val adapter = RecyclerAdapter()
adapter.sqlite = sqlite
adapter.pbList.addAll(sqlite.getPhoneBook())
이제 RecyclerAdapter의 Holder클래스 안에서 초기화 코드블록을 만든 뒤에 버튼의 리스너를 추가해야 합니다. 하지만 실제 삭제 동작을 수행하기 위해서는 RecyclerAdapter에 있는 pbList와 sqlite 쪽에 접근해야 하는데 Holder클래스는 RecyclerAdapter클래스 밑에서 별개로 존재하므로 Holder클래스를 통째로 RecyclerAdapter안으로 붙여넣은뒤 클래스 앞에 inner를 붙여서 Holder를 RecyclerAdapter클래스의 내부 클래스로 만들도록 합니다.
class RecyclerAdapter: RecyclerView.Adapter<RecyclerAdapter.Holder>() {
var pbList = mutableListOf<PhoneBook>()
var sqlite: SQLiteHelper? = null
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): Holder {
val view = LayoutInflater.from(parent.context).inflate(R.layout.phone_book_item, parent, false)
return Holder(view)
}
override fun onBindViewHolder(holder: Holder, position: Int) {
val pb = pbList.get(position)
holder.getPhoneBook(pb)
}
override fun getItemCount(): Int {
return pbList.size
}
inner class Holder(itemView: View): RecyclerView.ViewHolder(itemView) {
init {
itemView.btnDelete.setOnClickListener {
}
}
fun getPhoneBook(phoneBook: PhoneBook) {
itemView.tvSeq.text = "${phoneBook.seq.toString()}"
itemView.tvName.text = "${phoneBook.name}"
itemView.tvPhone.text = "${phoneBook.phone}"
}
}
}
그런 후 Holder클래스에서 PhoneBook을 저장할 수 있는 변수를 만들어 해당 변수에 현재의 데이터가 저장될 수 있도록 합니다. 이는 실제 원하는 항목의 데이터를 삭제하기 위해서는 현재 삭제 버튼의 입장에서 어떤 데이터가 표시되고 있는가를 알아야 하기 때문입니다.
inner class Holder(itemView: View): RecyclerView.ViewHolder(itemView) {
var pb: PhoneBook? = null
init {
itemView.btnDelete.setOnClickListener {
}
}
fun getPhoneBook(phoneBook: PhoneBook) {
itemView.tvSeq.text = "${phoneBook.seq.toString()}"
itemView.tvName.text = "${phoneBook.name}"
itemView.tvPhone.text = "${phoneBook.phone}"
pb = phoneBook
}
}
마지막으로 삭제버튼 클릭 시 SQLite의 DB 데이터와 리스트에서 해당 목록을 삭제하면 최종적으로 삭제 기능의 구현됩니다.
inner class Holder(itemView: View): RecyclerView.ViewHolder(itemView) {
var pb: PhoneBook? = null
init {
itemView.btnDelete.setOnClickListener {
sqlite?.removePhoneBook(pb!!)
pbList.remove(pb)
notifyDataSetChanged()
}
}
fun getPhoneBook(phoneBook: PhoneBook) {
itemView.tvSeq.text = "${phoneBook.seq.toString()}"
itemView.tvName.text = "${phoneBook.name}"
itemView.tvPhone.text = "${phoneBook.phone}"
pb = phoneBook
}
}
'Mobile > Kotlin' 카테고리의 다른 글
[Kotlin] 카메라 사용하기 (0) | 2020.12.31 |
---|---|
[kotlin] ORM라이브러리 Room (0) | 2020.12.30 |
[kotlin] SQLite - SQLite Open Helper 구현하기 (0) | 2020.12.29 |
[kotlin] androidx.preference (0) | 2020.12.28 |
[kotlin] Preferences (0) | 2020.12.28 |