안드로이드 스튜디오 메모 앱 만들기(6)

윤재환·2024년 11월 23일

메모 지우기

우선 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함수를 이용해서 리스트에서 삭제 시킵니다.

  • removeAtList에서 특정 위치(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())는 서로 다른 책임을 가집니다.
    • 데이터 작업: 리스트의 데이터를 변경하고 이를 저장.
    • UI작업 : RecyclerView의 화면을 갱신.
  • 이를 분리하면 코드의 가독성이 좋아지고, 문제가 발생했을 때 디버깅이 쉬워집니다.

다음 실습에서는 제목 입력을 추가로 작성해 보겠습니다.

    
profile
백엔드 개발에 관심있는 1인

0개의 댓글