[AndroidStudio,SpringBoot] KnockKnock 개발일지 - 0209 (게시글 댓글 삭제)

Hyebin Lee·2022년 2월 9일
0

knockknock 개발일지

목록 보기
23/29
post-thumbnail
post-custom-banner

오늘의 목표

  1. 게시글과 댓글 삭제 기능 구현하기
  2. 마이페이지 생성하기
  3. 게시글 조회와 작성에 따른 sharePoint 변화 주기 - 마이페이지에서 조회 가능

참고한 링크

1. [안드로이드] Retrofit2 기본 사용법2 -'GET/POST/PUT/DELETE'
2. [안드로이드 Java] 버튼 추가 하기, 숨기기, 비활성화 하기
3. How to access Shared Preferences for each item in Recycler View in Fragment
4. How to update RecyclerView Adapter Data

오늘의 이슈

RecyclerAdapter 에서 ItemView 추가/ 삭제/ 업데이트 즉각 반영하기

1. 유저에 따라 삭제 버튼 활성화/비활성화 하기

버튼을 보이게 하는 방법은 매우 단순했다.
xml 파일에서 일단 해당 버튼의 visibility 를 invisible로 설정해서 아무나 못보게 해놓은 후,
activity에서 지금 로그인 되어있는 유저의 아이디와 작성자의 아이디가 일치하면 해당 버튼의 visibility를 활성화 시키는 것이다.


id 변수는 이미지 상에서 보이지 않지만 위의 코드에서 sharedPreference로 로그인된 유저의 아이디를 참조하고 있는 상태다.
생각보다 버튼 활성화는 아주 쉬웠다!! 다행이야 😎

2. Retrofit Delete 통신

delete 통신은 안드로이드에서 처음 해보는 거라 조금 긴장했는데 메서드는 CRUD 중에서 가장 단순했다.

@DELETE("api/post/view/{postId}/delete")
    Call<Void> deletePost(@Path("postId")Long postId);

delete 통신 후 return 값이 없게 설정을 했으니 Call Void로 받아야 한다.

게시글 삭제는 아주 손 쉽게 이루어졌으나 문제는 댓글 삭제였다.
댓글 자체가 listView에 담겨져 있는게 전부라 각 listView마다 user와 작성자의 아이디를 비교하고 삭제버튼을 활성화하여 삭제하는 것이 난감했다....

🌟댓글 listView 아이템 각각에서 삭제 버튼 활성화하기

  1. CommentRecyclerAdapter에서 각 viewItem의 버튼 변수를 생성하고 sharedPreferences에서 로그인 정보를 갖고 온다.
    이 때 기존에 쓰는 sharedPreference 코드와 조금 바뀌는 것이 있으니 주의하자
    그리고 userId는 onBindViewHolder에서 써야하기 때문에 static전역변수로 미리 Adapter 클래스에서 지정해두었다.
 public class MyViewHolder2 extends RecyclerView.ViewHolder{
        TextView writer;
        TextView timestamp;
        TextView content;
       📌 Button btn_deletecomment;

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

            writer = (TextView) itemView.findViewById(R.id.tv_comment_nickname);
            timestamp = (TextView) itemView.findViewById(R.id.tv_comment_timestamp);
            content = (TextView)itemView.findViewById(R.id.tv_comment_content);
            📌btn_deletecomment = (Button)itemView.findViewById(R.id.btn_deletecomment);

            📌//현재 로그인되어있는 user의 id 갖고 오기
            SharedPreferences sharedPreferences = itemView.getContext().getSharedPreferences("UserInfo",Context.MODE_PRIVATE);
            userId = sharedPreferences.getString("userId","");
        }
    }
  1. onBindViewHolder 에서 원하는 기능 구현하기
 @Override
    public void onBindViewHolder(@NonNull CommentRecyclerAdapter.MyViewHolder2 holder, int position){

        holder.writer.setText(commentlist.get(position).getCommentWriterNickname());
        holder.content.setText(commentlist.get(position).getCommentContent());
        holder.timestamp.setText(commentlist.get(position).getCommentedTime());
        //로그인 계정과 댓글 작성자가 일치하는지 확인 후 일치하면 삭제 버튼 활성화 
       📌 if(commentlist.get(position).getCommentWriterId().equals(userId)){
            holder.btn_deletecomment.setVisibility(View.VISIBLE);
        holder.btn_deletecomment.setTag(commentlist.get(position).getCommentId());
        holder.btn_deletecomment.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Long commentid = (Long) view.getTag();
                PostAPI postAPI = RetrofitClient.getInstance().create(PostAPI.class);
                Call<Void> call = postAPI.deleteComment(commentid);
                call.enqueue(new Callback<Void>() {
                    @Override
                    public void onResponse(Call<Void> call, Response<Void> response) {
                        if(response.isSuccessful()){
                            Toast.makeText(c.getApplicationContext(), "댓글이 삭제되었습니다.", Toast.LENGTH_SHORT).show();

                        }
                        else{
                            Toast.makeText(c.getApplicationContext(), "댓글 삭제에 실패했습니다.", Toast.LENGTH_SHORT).show();
                            ErrorBody error = new Gson().fromJson(response.errorBody().charStream(),ErrorBody.class);
                            Log.d("CommentRecyclerAdapter",error.getMessage());
                        }
                    }

                    @Override
                    public void onFailure(Call<Void> call, Throwable t) {
                        Toast.makeText(c.getApplicationContext(), "댓글 삭제 연결 실패", Toast.LENGTH_SHORT).show();
                    }
                });


            }
        });
    }}

자 이렇게 각 댓글 listView Item에서 로그인 계정에 맞게 삭제 버튼도 활성화하고 삭제까지 잘 구현은 했는데
지금 한 가지 아쉬운 점은,, 삭제 하고 난 뒤에 페이지 refresh 가 안된다는 점이다..
그 말은 즉,, 삭제하고 나서 다른 페이지에 들어갔다가 다시 와야 삭제가 해당 화면에서 반영되지 삭제 버튼을 누르자마자 삭제가 반영되지 않았다.

이 부분은 삭제 작성이랑 똑같이 finish()를 startActivity()를 하면 될 줄 알았는데 ㅠㅠ Adapter 클래스 내에서는 해당 메소드를 사용할 수가 없었다...

3. RecyclerView 에서 ItemView 변화(등록,삭제,수정) 즉각 반영하기

How to update RecyclerView Adapter Data 다음 스택플로우 링크에서 많은 도움을 받았다!

의외로 삭제와 등록을 즉각으로 반영하는 코드는 매우 단순했다.
이거 지난번에 댓글 등록할 때도 엄청 헤맸고 결국 다른 코드로 어찌저찌 짜긴 했는데.. 왜 이 단순한걸 알지 못했을까

여튼!

int removeIndex = 2;
data.remove(removeIndex);
adapter.notifyItemRemoved(removeIndex);

삭제의 경우 위의 예시와 같이 삭제를 원하는 item의 position(index) 값을 받은 후
RecyclerAdapter 에서 멤버변수로 가지고 있는 (이후 각각 listView item으로 뽑아낼 ) 데이터 list에서 해당 index의 원소를 remove 시키고
이후 해당 index의 원소가 remove된걸 adapter가 반영할 수 있게 코드를 짜주면 된다.

 if(response.isSuccessful()){
      Toast.makeText(c.getApplicationContext(), "댓글이 삭제되었습니다.", Toast.LENGTH_SHORT).show();
      commentlist.remove(pos);
      notifyItemRemoved(pos);
                        }

위의 코드는 실제로 내가 댓글이 삭제된 후에 api로 DB에 반영하고 이후 처리를 코드로 작성한 것이다.
DB에 반영이 되었어도 adapter의 멤버변수로 남아있는 list에는 삭제가 반영이 안되어있기 때문에
따로 commentlist.remove를 해주고 그것을 감지하도록 코드를 짰다.

나머지 데이터 더하기, 데이터 수정 감지도 위의 스택플로우 링크에서 하라는 대로 간단하게 짤 수 있을 것이다.
어쨌든 adapter의 notify 함수의 핵심은 DB 변경을 notify하는 것이 아니라 자기의 멤버변수 list의 변경을 감지하는 것! 따라서 DB만 변경하지 말고 list에도 원소를 직접 넣어주고 notify해주면 된다!

post-custom-banner

0개의 댓글