Android (안드로이드)

[Android] 리사이클러뷰 아이템 수정, 삭제 / 리사이클러뷰 아이템 클릭 이벤트

Oscar:) 2024. 1. 19. 16:17

 

 

지난 포스팅에 이어 리사이클러뷰 마무리 포스팅이다.

 

아이템 클릭 이벤트 + 아이템 수정·삭제까지 진행해보자.

 

 

✅ 목차

 

- 어댑터에서의 아이템 클릭 이벤트

 

- 아이템 수정

 

- 아이템 삭제

 

- 인터페이스를 활용한 액티비티에서의 아이템 클릭 이벤트

 

 

 

 


 

어댑터에서의 아이템 클릭 이벤트

 

지난 리사이클러뷰 포스팅 코드를 재탕한다.

 

어댑터의 ViewHolder 부분만 보겠다.

 

 

RecyclerViewAdapter.java

class ViewHolder extends RecyclerView.ViewHolder {

    LinearLayout itemLayout;
    TextView nameText;
    TextView ageText;

    public ViewHolder(@NonNull View itemView) {
        super(itemView);

        itemLayout = itemView.findViewById(R.id.recyclerViewItem);
        nameText = itemView.findViewById(R.id.nameItemTextView);
        ageText = itemView.findViewById(R.id.hobbyItemTextView);

    }

    void onBind(Student student) {

        nameText.setText(student.getName());
        ageText.setText(String.valueOf(student.getHobby()));

        itemLayout.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {

                String[] array = {"수정", "삭제"};

                AlertDialog dialog = new AlertDialog.Builder(context)
                    .setItems(array, new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialogInterface, int i) {

                            if (i == 0) {

                                // 아이템 수정

                            } else {

                                // 아이템 삭제

                            }

                        }
                    })
                    .create();

                    dialog.show();

            }
        });

    } // onBind()

} // ViewHolder

 

 

아이템 레이아웃의 최상위 View를 참조하여

onBind() 메서드에서 클릭 리스너를 구현했다.

 

클릭 시 수정·삭제 버튼 형식의 다이얼로그를 띄워주었다.

 

 

결과는 다음과 같다.

 

 

아이템을 클릭하면 다이얼로그가 띄워진다.

 

 

 

다이얼로그를 사용하려면 Context가 필요한데,
어댑터에서 Context를 어떻게 얻나요?



어댑터 내 onCreateViewHolder() 메서드의 parent 인자를
어댑터 내 전역변수에 초기화하여 사용할 수 있다.

 

 

 


 

아이템 수정

 

 

이론은 되게 간단하다.

ArrayList의 데이터를 수정하고, Adapter에 알리기만 하면 된다.

 

하지만 '어떤' 아이템을 수정할 것인가 라는 문제가 있을 뿐이다.

결국 어댑터에서 아이템의 index 값을 받아와야 해결할 수 있다.

 

아이템의 index는 getAdapterPosition() 메서드로 해결할 수 있다.

 

 

onBind() 메서드 안의 itemLayout 클릭 리스너 부분만 보겠다.

View dialogView = LayoutInflater.from(context).inflate(R.layout.custom_dialog, null);
EditText nameEditText = dialogView.findViewById(R.id.dialogNameEditText);
EditText hobbyEditText = dialogView.findViewById(R.id.dialogHobbyEditText);

if (i == 0) {

    // 아이템 수정
    new AlertDialog.Builder(context)
        .setView(dialogView)
        .setPositiveButton("완료", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialogInterface, int i) {

                String name = nameEditText.getText().toString();
                String hobby = hobbyEditText.getText().toString();

                arrayList.set(getAdapterPosition(), new Student(name, hobby));
                notifyDataSetChanged();

            }
        })
        .create()
        .show();

}

 

 

커스텀 다이얼로그를 띄우고, 완료 버튼을 누르면

EditText로 받아온 값으로 ArrayList를 수정해주고 notify() 해주었다.

 

 

결과는 다음과 같다.

 

 

 

오스카의 취미가 축구 → 낚시로 수정되었다.

 

 


 

아이템 삭제

 

 

아이템 수정을 해냈다면 삭제는 훨씬 간단하다.

 

마찬가지로 삭제할 아이템의 index 값을 받아와서

ArrayList에서 삭제해주고, 리사이클러뷰에 초기화해주면 그만이다.

 

 else {
 
    // 아이템 삭제
    arrayList.remove(getAdapterPosition());
    notifyDataSetChanged();

}

 

getAdapterPosition() 메서드를 활용하여

ArrayList에서 해당 아이템을 삭제해줬다.

 

 

결과는 다음과 같다.

 

 

 

 


 

인터페이스를 활용한 액티비티에서의 아이템 클릭 이벤트

 

 

개발을 하다보면 어댑터에서 모든 작업을 처리하기엔 번거로울 때가 많다.

액티비티에서 가지고 있는 데이터나 View 등을 처리해야 할 상황이 많기 때문이다.

 

인터페이스를 활용하여 아이템 클릭 리스너를 액티비티에서 사용해보자.

 

 

 

먼저, 어댑터에 인터페이스를 만들어주자.

 

 

RecyclerViewAdapter.java

public interface OnItemClickListener {
    void onItemClicked(View view, int position);
}

 

 

인터페이스 이름과 메서드 이름은 자유롭게 지어도 된다.

 

 

그리고 이 인터페이스를 액티비티와 연결해줘야 하는데,

생성자를 이용해보겠다.

 

 

RecyclerViewAdapter.java

OnItemClickListener listener;

public RecyclerViewAdapter(OnItemClickListener listener) {
    this.listener = listener;
}

 

 

그리고 ViewHolder에 있던 아이템 클릭 이벤트를 보자.

 

 

RecyclerViewAdapter.java

itemLayout.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View view) {

        listener.onItemClicked(view, getAdapterPosition());
        
        // 이전에 작성한 내용 모두 주석 처리.
        
    }
});

 

위에서 했던 과정을 쭉 따라왔다면, 지금 이 부분이 상당히 지저분할 것이다.

(다이얼로그 띄워주는 코드, 수정·삭제 코드 등)

 

모두 주석 처리해버리고, 방금 만들어준 인터페이스의 메서드를 작성해주자.

 

 


 

이제 액티비티로 돌아가서 작업을 해준다.

 

 

RecyclerViewActivity.java

public class RecyclerViewActivity extends AppCompatActivity
implements RecyclerViewAdapter.OnItemClickListener {

    RecyclerViewAdapter adapter;

    ...

    adapter = new RecyclerViewAdapter(this);

    @Override
    public void onItemClicked(View view, int position) {

        // TODO

    }

}

 

 

아까 어댑터에서 만들어준 인터페이스를 implements 해주고,

해당 메서드를 Override해준다.

 

그리고 어댑터에 생성자를 만들었으니 초기화할 때 인수로 넣어준다.

 

 

이제 어댑터의 ViewHolder 안에서 작업했던 내용을 가져와 (주석 처리한 부분)

저 TODO 부분에서 처리해주면 끝이다 !

 

 

 

RecyclerViewActivity.java

@Override
public void onItemClicked(View view, int position) {

    String[] array = {"수정", "삭제"};

    View dialogView = LayoutInflater.from(RecyclerViewActivity.this).inflate(R.layout.custom_dialog, null);
    EditText nameEditText = dialogView.findViewById(R.id.dialogNameEditText);
    EditText hobbyEditText = dialogView.findViewById(R.id.dialogHobbyEditText);

    nameEditText.setText(arrayList.get(position).getName());
    hobbyEditText.setText(arrayList.get(position).getHobby());

    AlertDialog dialog = new AlertDialog.Builder(RecyclerViewActivity.this)
        .setItems(array, new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialogInterface, int i) {

                if (i == 0) {

                    new AlertDialog.Builder(RecyclerViewActivity.this)
                        .setView(dialogView)
                        .setPositiveButton("완료", new DialogInterface.OnClickListener() {
                            @Override
                            public void onClick(DialogInterface dialogInterface, int i) {

                                String name = nameEditText.getText().toString();
                                String hobby = hobbyEditText.getText().toString();

                                arrayList.set(position, new Student(name, hobby));
                                adapter.setItem(arrayList);

                            }
                        })
                        .create()
                        .show();

                    } else {

                        arrayList.remove(position);
                        adapter.setItem(arrayList);

                }
            }
        })
        .create();

    dialog.show();

}

 

 

어댑터의 코드를 그대로 복붙해 왔다면, 이곳 저곳이 빨간줄일 것이다.

눈치껏 알맞게 바꿔주면 된다.

 

getAdapterPosition() → 메서드의 position 인자
데이터 클래스 → ArrayList.get(position)
Context → ActivityContext

 

 

 

결과는 다음과 같다.

 

 

어댑터에서 처리했을 때처럼, 수정·삭제가

정상적으로 작동하는 것을 볼 수 있다.

 

 

인터페이스부터 시작해서 여기저기 세팅할 부분이 늘어나는 감이 있지만,

그래도 액티비티에서 클릭 이벤트를 처리하는게 더 편하다고 느낀다.

 

 

 

 


 

 

 

 

리사이클러뷰는 앞으로도 많이 사용할 위젯이다.

 

어렵더라도 많이 친근해졌으면 좋겠다.