마스터Q&A 안드로이드는 안드로이드 개발자들의 질문과 답변을 위한 지식 커뮤니티 사이트입니다. 안드로이드펍에서 운영하고 있습니다. [사용법, 운영진]

안드로이드 파이어베이스 데이터베이스 질문입니다.

0 추천

안녕하세요 안드로이드 스튜디오로 개발하고 있는 개발 뉴비입니다.

제가 파이어베이스 파이어스토어를 사용하여 개발하는데 공식 문서를 읽어도 어떻게 해야 할 지 몰라서 글을 올립니다. 

파이어스토어에서 user라는 컬렉션안에 해당 유저의 이메일을 저장 시키고 그 안에 필드로 여러값을 저장 시키게 했습니다.

 

대충 이렇게 되어있는데 여기서 userName이라는 내용만 따로 서버에서 받아서 다시 다른 컬렉션쪽으로 보내서 저장 시키고 싶은데 혹시 어떻게 해야 하나요?

언어는 코틀린으로 사용합니다.

kiop (160 포인트) 님이 2022년 3월 23일 질문

1개의 답변

0 추천

결국은 개발 문서를 보시고 하셔야 해요. 이해가 안가시는 이유는 개발문서를 읽는 법에 익숙하지 않거나, 파이어베이스 구조를 이해하지 못하셨거나, Kotlin 사용에 어려움이 있으신 것이니 필요한 부분은 더 찾아보시기 바랍니다.

먼저, 개발문서에 나온 대로 처리하면 됩니다.
읽어오기: https://firebase.google.com/docs/firestore/query-data/get-data#get_a_document
저장하기: https://firebase.google.com/docs/firestore/manage-data/add-data#set_a_document

// 제 기억으로는 파이어베이스에 사용하는 데이터 클래스는 val가 아니라 var을 사용해야 
// 제대로 동작을 했던 같은데, 변경되었을 수도 있으니 val로드 확인을 해보세요.
data class User (
   var point: Int,
   var userAge: Int,
   var userEmail: String,
   var userName: String,
   var userImage: String
)


interface DocumentListener {
     fun onSuccess(user: User)
     fun onFailure(e: Exception)
}

class UserRepository {
   private val doc by lazy { db.collection("your_collection_name") }

   fun getUser(email: String,  listener: DocumentListener ) {
    doc.document(email)
        .get()
        . addOnCompleteListener { task ->
            if (task.exception != null) {
                 listener.onFailure(task.exeption)
                 return
            }

            user = document.data.toObject(User::class.java)
            listener.onSuccess(user)
        }
   }


   fun saveUser(user: User, listener: DocumentListener) {
      docdocument(user.userEmail)
             .set(user)
              addOnCompleteListener { task ->
                 if (task.exception != null) {
                     listener.onFailure(task.exeption)
                     return
                 }

                listener.onSuccess(user)
        }
   }
}

 

// 액티비티나 프레그먼트 등의 뷰에서 필요한 코드

private val userRepository by lazy { UserRepository() }
private var user: User? = null

// User를 읽어오는 코드
fun fetchUser() {
    userRepository.getUser("test@test.com", object: DocumentListener {
        override fun onSuccess(user: User) {
           this.user = user
        }

        override fun onFailure(e: Exception) {
            // 에러처리
        }
    })
}


// User의 이메일을 변경하여 저장하는 코드
fun saveUser() {
   if (user == null) {
        // 필요시 에러처리
        return
   }

   val testUser = user!!.copy(userEmail = "새로운 이메일 주소")
   userRepository.saveUser(testUser, object: DocumentListener {
       override fun onSuccess(user: User) {
          // 성공처리
          this.user = user
       }

       override fun onFailure(e: Exception) {
          // 에러처리
       }
   })
}

fun saveUser(user: User) {
   userRepository.saveUser(user, , object: DocumentListener {
       override fun onSuccess(user: User) {
          // 성공처리
       }

       override fun onFailure(e: Exception) {
          // 에러처리
       }
   })
}

대체로 위와 같은 흐름이 되므로, 모든게 비동기로 동작하므로, 위처럼 콜백을 사용하셔서 콜백 함수 내에서 결과를 받아오도록 처리를 하시던가, 코루틴을 사용하실 수 있다면 콜백을 코루틴으로 변경하면 비동기지만 동기식으로 보이는 코드를 작성할 수 있습니니다. 기본적으로 콜백함수를 사용하는 법을 이해하지 못하시면 해당 기능 구현이 어려우실 테니 그 부분을 공부하시길 바랍니다.

spark (226,420 포인트) 님이 2022년 3월 24일 답변
spark님이 2022년 3월 24일 수정
참고로 UserRepository에 콜백을 사용하실 때 라이프사이클도 처리해주시는 것이 안전한데,  아래와 같은 형태로 onStop에서 리스너를 해제하고 onStart에서 등록하는 부분이 필요할 것 같습니다.

class UserRepository(
  var listener: DocumentListener? = null
) {
   private val doc by lazy { db.collection("your_collection_name") }
 
   fun getUser(email: String) {
    ...
           if (task.exception != null) {
                 listener?.onFailure(task.exeption)
                 return
            }
 
           ...
            listener?.onSuccess(user)
   }
 
 
   fun saveUser(user: User) {
      ...
       if (task.exception != null) {
                 listener?.onFailure(task.exeption)
                 return
            }
 
           ...
            listener?.onSuccess(user)
   }
}

class MyActivity: AppCompatActivity, DocumentListener {
  private val userRepository by lazy { UserRepository() }
  private var user: User? = null
 
   fun fetchUser() {
      userRepository.getUser("test@test.com")
   }
 
   fun saveUser() {
      ...
      userRepository.saveUser(testUser)
   }
 
   fun saveUser(user: User) {
        userRepository.saveUser(user)
   }

     override fun onStart() {
       super.onStart()
       userRepository.listener = this
     }

      override fun onStop() {
       super.onStart()
       userRepository.listener = null
     }

     override fun onSuccess(user: User) {
         this.user = user
         // 성공처리
     }
 
     override fun onFailure(e: Exception) {
         // 에러처리
     }

}
...