App/Android Native

Clone project - Book App - Step 9 (comments)

Agrafenaaa 2021. 12. 29. 02:07

결과화면

 

1. AdapterComment - onBindViewHolder

- date를 다시 long으로 변환시켜줄 것(addcomment 메서드 실행 때 string으로 저장함)

- deleteComment는 removeValue()만 하면 되므로 기술 생략

 override fun onBindViewHolder(holder: HolderComment, position: Int) {
        //init auth
        firebaseAuth = FirebaseAuth.getInstance()

        //get data
        val model = commentArrayList[position]
        val date = MyApplication.formatTimeStamp(model.timestamp.toLong())

        holder.dateTv.text = date
        holder.commentTv.text = model.comment

        //get profileImage and name of the user
        loadUserDetails(model, holder)
        //delete comment
        holder.itemView.setOnClickListener {
            //check if the user logged in and matches the writer of the comment
          if(firebaseAuth.currentUser != null && firebaseAuth.currentUser!!.uid == model.uid){
                deleteCommentDialog(model, holder)
          }else if(firebaseAuth.currentUser == null){
              Toast.makeText(context, "Please log in", Toast.LENGTH_SHORT).show()
          }else if(firebaseAuth.currentUser!!.uid != model.uid){
              Toast.makeText(context, "The comment made by another user", Toast.LENGTH_SHORT).show()
          }
        }
    }

 

2. AdapterComment - loadUserDetails

- model과 holder를 매개변수로 받아 다른 Reference(즉 Books가 아닌 Users)의 정보 불러오기

private fun loadUserDetails(model: ModelComment, holder: AdapterComment.HolderComment) {
        val ref = FirebaseDatabase.getInstance().getReference("Users")

        ref.child(model.uid)
            .addListenerForSingleValueEvent(object: ValueEventListener{
                override fun onDataChange(snapshot: DataSnapshot) {
                    //get data
                    val name = "${snapshot.child("name").value}"
                    val profileImage = "${snapshot.child("profileImage").value}"

                    //set data
                    holder.nameTv.text = name
                    try{
                        Glide.with(context)
                            .load(profileImage)
                            .into(holder.profileIv)
                    }catch(e: Exception){
                        holder.profileIv.setImageResource(R.drawable.ic_person_gray)
                    }
                }
                override fun onCancelled(error: DatabaseError) {
                }
            })
    }

 

3. PdfDetailActivity - addComentDialog() / addComent()

- comment input layout을 dialog형식으로 출력

- timestamp를 child id로 설정

private fun addCommentDialog() {
        //inflate dialog_comment_add.xml
        val commentAddBinding = DialogCommentAddBinding.inflate(LayoutInflater.from(this))

        //setup alert dialog w transparent bg
        val builder = AlertDialog.Builder(this, R.style.customDialog)
        builder.setView(commentAddBinding.root)

        val alertDialog = builder.create()
        alertDialog.show()

        commentAddBinding.backBtn.setOnClickListener {
            alertDialog.dismiss()
        }

        // add comment to DB
        commentAddBinding.submitBtn.setOnClickListener {
            comment = commentAddBinding.commentEt.text.toString().trim()
            if(comment.isEmpty()){
                Toast.makeText(this, "Leave your comment!", Toast.LENGTH_SHORT).show()
            }else{
                alertDialog.dismiss()
                addComment()
            }
        }
    }

    private fun addComment() {
        //progress
        progressDialog.setMessage("Adding comment")
        progressDialog.show()

        //set data
        val timestamp = "${System.currentTimeMillis()}"
        val hashMap = HashMap<String, Any>()
        hashMap["id"] = "$timestamp"
        hashMap["bookId"] = "$bookId"
        hashMap["timestamp"] = "$timestamp"
        hashMap["comment"] = "$comment"
        hashMap["uid"] = "${firebaseAuth.uid}"

        //update to DB
        val ref = FirebaseDatabase.getInstance().getReference("Books")
        ref.child(bookId).child("comments").child(timestamp)
            .setValue(hashMap)
            .addOnSuccessListener {
                progressDialog.dismiss()
                Toast.makeText(this, "Comment has been added", Toast.LENGTH_SHORT).show()
            }
            .addOnFailureListener { e ->
                progressDialog.dismiss()
                Toast.makeText(this, "failed to add comment. Error: ${e.message}", Toast.LENGTH_SHORT).show()
            }
    }

 

4. PdfDetailActivity - loadComments() <- RecylerView 삽입

private fun loadComments() {
        // init arr
        commentArrayList = ArrayList()

        val ref = FirebaseDatabase.getInstance().getReference("Books")
        ref.child(bookId).child("comments")
            .addValueEventListener(object: ValueEventListener{
                override fun onDataChange(snapshot: DataSnapshot) {
                    // clear list
                    commentArrayList.clear()

                    for(ds in snapshot.children){
                        val comment = ds.getValue(ModelComment::class.java)
                        commentArrayList.add(comment!!)
                    }

                    // set adapter
                    adapterComment = AdapterComment(this@PdfDetailActivity, commentArrayList)
                    // set RecyclerView
                    binding.commentsRv.adapter = adapterComment
                }

                override fun onCancelled(error: DatabaseError) {
                }
            })
    }

 

 

 

중간에 또 firebase 오류가 생기고 이번에 건들지도 않은 FileNotFoundException부터 시작해서 온갖 런타임 에러가 떴다.

Как всегда... даром не пройдет 😂

이것저것 하다가 디버깅이 되긴 했으나 정확히 어떤 부분이었는지는 모르겠다. 

우선 내가 취한 조치는 하기와 같다. 

- google-service.json 재삽입 (프로젝트 손 안 댄지 한 한 달 지남)

- firebase-crashlytics depedency 삭제 (애초에 사용하지 않지만 뭐 하다가 주입했지만 이전에는 전혀 문제가 되지 않았음)

- firebase-analytics, database 각 0.1씩 업데이트

 

 

Ref: https://www.youtube.com/channel/UCT132T980-1lhm0hcZFy4ZA