우선 item_memo.xml 입니다.
<TextView
android:id="@+id/textViewMemo"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:textSize="16sp" />
<!-- 메모 삭제 버튼 -->
<Button
android:id="@+id/buttonDeleteMemo"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="삭제"/>
layout_weight="1": TextView가 가로 공간을 최대로 차지하도록 설정했습니다.
Button : 삭제 버튼을 추가하고 공간은 글자 크기에 맞췄으며 아이디는 buttonDeleteMemo로 설정하였습니다.
다음은 Memoadapter입니다.
package com.xml.androidlab
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Button
import android.widget.TextView
import androidx.recyclerview.widget.RecyclerView
class MemoAdapter(private val memoList: MutableList<String>, // 기존 List에서 MutableList로 변경
private val onDelete: (Int) -> Unit //삭제 콜백 추가
) : RecyclerView.Adapter<MemoAdapter.MemoViewHolder>() {
// ViewHolder 클래스 정의
class MemoViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
val textViewMemo: TextView = itemView.findViewById(R.id.textViewMemo)
val buttonDeleteMemo: Button = itemView.findViewById(R.id.buttonDeleteMemo)
}
// onCreateViewHolder: 아이템 레이아웃을 생성하여 ViewHolder에 전달
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MemoViewHolder {
val view = LayoutInflater.from(parent.context).inflate(R.layout.item_memo, parent, false)
return MemoViewHolder(view)
}
// onBindViewHolder: ViewHolder에 데이터를 바인딩
override fun onBindViewHolder(holder: MemoViewHolder, position: Int) {
holder.textViewMemo.text = memoList[position]
//삭제 버튼 클릭 이벤트 처리
holder.buttonDeleteMemo.setOnClickListener{
onDelete(position) // 삭제 콜백 호출
}
}
// getItemCount: 아이템의 개수를 반환
override fun getItemCount(): Int = memoList.size
}
먼저 MemoAdapter클래스에 기존에 List로 되어 있던걸 MutableList로 바꿔주어 수정이 가능하게 만들고 아까 만든 메모 삭제 버튼을 참조하게 만들었습니다.
이후 onBindViewHolder메서드에 삭제 버튼 이벤트를 추가 하였습니다.
onDelete(position): 어댑터에 전달된 onDelete 콜백 함수를 호출하여, 현제 position에 해당 위치의 메모를 삭제하는 기능을 만들었습니다.다음은 MainActivity.kt입니다.
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
// EditText, Button, RecyclerView 참조
val editTextMemo = findViewById<EditText>(R.id.editTextMemo)
val buttonAddMemo = findViewById<Button>(R.id.buttonAddMemo)
val recyclerViewMemos = findViewById<RecyclerView>(R.id.recyclerViewMemos)
// RecyclerView 설정
recyclerViewMemos.layoutManager = LinearLayoutManager(this)
adapter = MemoAdapter(memoList) { position ->
deleteMemo(position) // 삭제 처리
}
recyclerViewMemos.adapter = adapter
// 저장된 메모 불러오기
loadMemos()
// 버튼 클릭 이벤트
buttonAddMemo.setOnClickListener {
val memoText = editTextMemo.text.toString()
if (memoText.isNotEmpty()) {
memoList.add(memoText) // 메모 리스트에 추가
adapter.notifyDataSetChanged() // 어댑터에 변경 사항 반영
editTextMemo.text.clear() // 입력 필드 초기화
saveMemos() // 메모 저장
}
}
}
RecyclerView 설정의 adapter에 메모 삭제 기능을 구현하기 위해 람다식을 통해 삭제 콜백을 전달하는 코드를 추가 했습니다.
//메모 삭제 처리
private fun deleteMemo(position: Int){
memoList.removeAt(position) //리스트에서 삭제
adapter.notifyDataSetChanged() //RecyclerView업데이트
saveMemos() // 변경된 메모 저장
}
이후 추가로 메모 삭제 처리하는 메서드를 추가로 작성 했습니다
memoList에서 removeAt함수를 이용해서 리스트에서 삭제 시킵니다.
removeAt는 List에서 특정 위치(index)에 있는 아이템을 제거하는 메서드 입니다.notifyDataSetChanged()함수를 이용해서 recyclerView를 업데이트 한후에 saveMemos를 로 저장 합니다.
해당 코드를 짜면서 왜 notifyDataSetChanged함수를 써서 업데이트 후에 savememos로 저장을 할까 고민 했습니다.
그양 바로 저장을 하면 안될까 라는 생각이 들었거든요.
이후 검색을 통해 알아봤습니다.
1. UI와 데이터 동기화
RecyclerView는 화면에 표시되는 데이터(View)와 데이터 리스트(memoList)를 동기화 해야합니다.memoList)만 변경하고 화면을 업데이트 하지 않으면, 사용자는 삭제된 데이터가 아직 화면에 표시되고 있다고 오해할 수 있습니다.adapter.notifyDataSetChanged()는 화면 (UI)을 현재 데이터 상태와 일치시키는 역할을 합니다.위 내용을 요약 하면 데이터(memoList)상으로는 삭제는 되어있지만 화면에서는 업데이트(새로고침)이 되지 않아 데이터가 남아 있는 모습을 보인다는 이야기 입니다.
2. 데이터와 UI작업 분리
memoList.removeAt(position)및saveMemos()와 UI작업 (adapter.notifyDataSetChanged())는 서로 다른 책임을 가집니다.RecyclerView의 화면을 갱신.다음 실습에서는 제목 입력을 추가로 작성해 보겠습니다.