인프런 커뮤니티 질문&답변

신예리님의 프로필 이미지

작성한 질문수

[초급편] 안드로이드 커뮤니티 앱 만들기(Android Kotlin)

댓글 불러오기

댓글 수정 및 삭제 구현 관련해 질문드립니다

해결된 질문

22.08.29 03:56 작성

·

1.1K

1

안녕하세요 선생님, [초급편] 안드로이드 커뮤니티 앱 만들기를 완강한 수강생입니다. 게시글 수정/삭제 파트와 아래 두 질문을 참고해가며 현재 댓글 수정/삭제를 구현하기 위해 애쓰는 중인데, 잘 되지 않아 질문드립니다.

https://www.inflearn.com/questions/411607

https://www.inflearn.com/questions/619233

게시글 설정과 마찬가지로 내가 쓴 댓글에만 보이는 설정 버튼을 클릭하면

다이얼로그를 통해 수정/삭제로 진입하게끔 만드는 데 까지는 성공했습니다.

첫 번째 질문입니다.

우선 수정 기능의 경우 아래 ????? 부분에 어떤 값을 넣어야 할지 감이 안 옵니다.

BoardReadActivity.kt


        // 댓글 클릭하면 -> 대화상자 뜸
        // 파이어베이스의 댓글 키를 기반으로 댓글 데이터(=본문+uid+시간) 받아옴
        cLV.setOnItemClickListener { parent, view, position, id ->

            // 명시적 인텐트 -> 다른 액티비티 호출
            val intent = Intent(baseContext, CommentEditActivity::class.java)

            // 댓글수정 액티비티로 댓글의 키 값 전달
            intent.putExtra("?????", ?????)

            // 댓글수정 액티비티 시작
            startActivity(intent)

        }

"key", key를 넣으면 댓글이 아닌 게시글의 키 값이 되어 댓글이 수정되지 않고,

"commentKey", commentKey를 넣으면 앱이 죽습니다.

게시판 프래그먼트에서 리스트뷰 아이템을 클릭하면 게시글로 이동하듯

댓글 리스트뷰 아이템을 클릭하면 수정 액티비티로 넘어가는 것도 시도해봤는데요,

빨간색이 게시글의 키, 파란색이 댓글의 키일 때 다행히 댓글의 키는 잘 받아오는데

댓글의 키'만' 알다보니 파이어베이스로부터 기존 댓글 내용을 받아올 수도, 수정한 내용을 업데이트 할 수도 없습니다.

BoardReadActivity.kt


// 댓글 클릭하면 -> 대화상자 뜸
// 파이어베이스의 댓글 키를 기반으로 댓글 데이터(=본문+uid+시간) 받아옴
cLV.setOnItemClickListener { parent, view, position, id ->

    // 명시적 인텐트 -> 다른 액티비티 호출
    val intent = Intent(baseContext, CommentEditActivity::class.java)

    // 댓글수정 액티비티로 댓글의 키 값 전달
    intent.putExtra("commentKey", commentKeyList[position])

    // 댓글수정 액티비티 시작
    startActivity(intent)

}

다이얼로그에서 댓글수정 액티비티로 넘길 때와 마찬가지로 ????? 부분에 어떤 값을 넣어야 할지 모르겠습니다.

CommentEditActivity.kt


// 댓글을 수정
private fun editCommentData(commentKey: String) {

    // 수정한 값으로 업데이트
    FBRef.commentRef.?????.child(commentKey).setValue(CommentModel(

        // 제목 및 본문은 직접 수정한 내용으로,
        binding.commentMainArea.text.toString(),

        // uid와 시간은 자동 설정됨
        FBAuth.getUid(),
        FBAuth.getTime()

    ))

    // 수정 확인 메시지
    Toast.makeText(this, "댓글이 수정되었습니다", Toast.LENGTH_SHORT).show()

    // 댓글수정 액티비티 종료
    finish()

}

혼자 해결하려니 너무 맨 땅에 헤딩이라ㅠㅠ 질문 올립니다.

답변 1

1

신예리님의 프로필 이미지
신예리
질문자

2022. 08. 29. 04:04

두 번째 질문도 비슷한 내용이라 그냥 이 글에 댓글로 올립니다.

// 댓글 삭제 버튼
commentAlertDialog.findViewById<ConstraintLayout>(R.id.commentDelete)?.setOnClickListener {

    FBRef.commentRef.?????.child(commentKey).removeValue()

    // 삭제 확인 메시지
    Toast.makeText(this, "(test)댓글이 삭제되었습니다", Toast.LENGTH_SHORT).show()

}

얘도 ????? 부분에 들어갈 값을 잘 모르겠어서 도움 요청드립니다.

전체 코드는 아래 깃허브에 업로드 해 놓았습니다.

https://github.com/shinyelee/my-solo-life

개복치개발자님의 프로필 이미지
개복치개발자
지식공유자

2022. 08. 29. 19:43

안녕하세요 예리님...

요게 처음에 하다보면 엄청 헷갈리는 부분인데... 천천히 하나씩 해볼게요.

지금 하신 것을 보니 충분히 혼자서 잘 하실 수 있으실 것 같아 방향을 설명드리겠습니다.

  1. 댓글을 불러온다(Firebase에서) -> 요것들은 잘 받아오셨네요

  2. 가져온 댓글 중에 key 값을 가져온다

  3. 그리고 댓글을 가져오려면 게시글의 key값도 필요하겠죵? 그러니깐 게시글의 key값과 댓글의 key값을 모두 수정하는 액티비티로 넘겨준다

  4. 수정 액티비티에서 게시글의 key / 댓글의 key를 바탕으로 수정을 원하는 게시글을 찾아서 업데이트 해준다.

이런식으로 구현하면 되지 않을까요?

신예리님의 프로필 이미지
신예리
질문자

2022. 08. 31. 01:59

해결했습니다!

BoardReadActivity.kt

생략

// 파이어베이스의 댓글 키를 기반으로 댓글 데이터(=본문+uid+시간) 받아옴
cLV.setOnItemClickListener { parent, view, position, id ->

    // 명시적 인텐트 -> 다른 액티비티 호출
    val intent = Intent(baseContext, CommentEditActivity::class.java)

    // 댓글수정 액티비티로 댓글의 키 값 전달
    intent.putExtra("key", key)

    // 댓글수정 액티비티로 댓글의 키 값 전달
    intent.putExtra("commentKey", commentKeyList[position])

    // 댓글수정 액티비티 시작
    startActivity(intent)

}

생략

설명해주신대로 boardRef의 게시글 key 값과 commentRef의 댓글 key 값을 받아와 수정 액티비티에 전달해주고

CommentEditActivity.kt

생략

class CommentEditActivity : AppCompatActivity() {

    // (전역변수) 바인딩 객체 선언
    private var vBinding : ActivityCommentEditBinding? = null

    // 매번 null 확인 귀찮음 -> 바인딩 변수 재선언
    private val binding get() = vBinding!!

    // 게시글 키
    private lateinit var key: String

    // 댓글 키
    private lateinit var commentKey: String

    // 태그
    private val TAG = CommentEditActivity::class.java.simpleName

    override fun onCreate(savedInstanceState: Bundle?) {

        super.onCreate(savedInstanceState)

        // 자동 생성된 뷰바인딩 클래스에서의 inflate 메서드 활용
        // -> 액티비티에서 사용할 바인딩 클래스의 인스턴스 생성
        vBinding = ActivityCommentEditBinding.inflate(layoutInflater)

        // getRoot 메서드로 레이아웃 내부 최상위에 있는 뷰의 인스턴스 활용
        // -> 생성된 뷰를 액티비티에 표시
        setContentView(binding.root)

        생략

        // 게시판 프래그먼트에서 게시글의 키 값을 받아옴
        key = intent.getStringExtra("key").toString()

        // 글읽기 액티비티에서 댓글의 키 값을 받아옴
        commentKey = intent.getStringExtra("commentKey").toString()

        // 댓글 키 값을 바탕으로 댓글 하나의 정보를 가져옴
        getCommentData(key, commentKey)

        // 수정하기 버튼을 클릭하면
        binding.commentEditBtn.setOnClickListener {

            // 키 값을 바탕으로 불러온 게시글을 수정
            editCommentData(key, commentKey)

        }

    }

    // 댓글을 수정
    private fun editCommentData(key: String, commentKey: String) {

        // 수정한 값으로 업데이트
        FBRef.commentRef.child(key).child(commentKey).setValue(CommentModel(

            // 제목 및 본문은 직접 수정한 내용으로,
            binding.commentMainArea.text.toString(),

            // uid와 시간은 자동 설정됨
            FBAuth.getUid(),
            FBAuth.getTime()

        ))

        // 수정 확인 메시지
        Toast.makeText(this, "댓글이 수정되었습니다", Toast.LENGTH_SHORT).show()

        // 댓글수정 액티비티 종료
        finish()

    }

    // 댓글 하나의 정보를 가져옴
    private fun getCommentData(key: String, commentKey: String) {

        // 데이터베이스에서 컨텐츠의 세부정보를 검색
        val postListener = object : ValueEventListener {

            // 데이터 스냅샷
            @SuppressLint("NotifyDataSetChanged")
            override fun onDataChange(dataSnapshot: DataSnapshot) {

                // 예외 처리
                try {

                    // 데이터 스냅샷 내 데이터모델 형식으로 저장된 아이템(=게시글)
                    val item = dataSnapshot.getValue(CommentModel::class.java)

                    // 본문 해당 영역에 넣음(작성자 및 시간은 직접 수정하지 않음)
                    binding.commentMainArea.setText(item?.main)
                    // textView -> .text
                    // editText -> .setText(집어넣을 데이터)

                    // 오류 나면
                } catch (e: Exception) {

                    // 로그
                    Log.e(TAG, "getBoardData 확인")

                }

            }
            // getCommentListData()와 달리 반복문이 아님 -> '단일' 아이템

            // 오류 나면
            override fun onCancelled(databaseError: DatabaseError) {

                // 로그
                Log.w(TAG, "loadPost:onCancelled", databaseError.toException())

            }

        }

        // 파이어베이스 내 데이터의 변화(추가)를 알려줌
        FBRef.commentRef.child(key).child(commentKey).addValueEventListener(postListener)

    }

    생략

}

파이어베이스 경로도 수정하니 정상적으로 삭제됩니다!