Kotlin

파이어베이스에서 읽어오는 데이터 값이 저장이 되지 않습니다.

0
class LogInActivity : AppCompatActivity() { var userId = "" var pcType = "" var nickName = "" override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) set..
class LogInActivity : AppCompatActivity() {
    var userId = ""
    var pcType = ""
    var nickName = ""
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_log_in)

        val db: DatabaseReference = Firebase.database.reference

        // 이미 로그인이 되어있는 경우
        UserApiClient.instance.accessTokenInfo { tokenInfo, error ->
            if (error != null) {
                Log.e("Token", "토큰 정보 보기 실패")
            } else if (tokenInfo != null) {
                Log.d("Token", "토큰 정보 보기 성공")

                UserApiClient.instance.me { user, error ->
                    if (error != null) {
                        Log.e("TAG", "사용자 정보 요청 실패", error)
                    } else if (user != null) {
                        val id = user.id.toString()
                        setId(id)

                        db.child("users").child(id).child("type").get().addOnSuccessListener {
                            val dbType = it.value.toString()
                            Log.i("info t", dbType.toString())
                            setType(dbType)
                        }.addOnFailureListener {
                            Log.e("firebase", "Error getting data", it)
                        }

                        db.child("users").child(id).child("nickname").get().addOnSuccessListener {
                            val nick = it.value.toString()
                            Log.i("info nick", nick)
                            nickName = nick
                        }.addOnFailureListener {
                            Log.e("firebase", "Error getting data", it)
                        }



/*************************/

    private fun setId(id : String) {
        userId = id
    }

    private fun setType(t : String) {
        pcType = t
    }

데이터 저장에 필요 변수는 전역으로 설정해주었습니다.

db.child("users").child(id.toString()).child("type").get().addOnSuccessListener {

이 부분의 중괄호 내에서 dbType 변수에 데이터가 잘 저장된 걸 확인했습니다. 또한 전역변수로 선언해놓은 pcType에도 저장이 되어있습니다.

하지만 위 코드의 중괄호를 나가게 되면 pcType 변수에 다시 null 값이 들어 가 있습니다.

 

nickName 처럼 set 메소드를 안 쓰고 직접 저장을 해도 똑같이 중괄호를 나가면 다시 null 값으로 돌아갑니다.

이와 마찬가지로 UserApiClient.instance.me에서 저장되는 id값도 중괄호를 벗어나면 null 값으로 됩니다..

며칠 전만 해도 문제 없이 잘 저장되었던 걸로 알고 있었는데 갑자기 변수에 값이 저장이 안되니 막막합니다..

 

제가 코틀린을 잘못 이해하고 사용하고 있는 것인가요?

파이어베이스에서 가져온 데이터 값을 어떻게 해야 변수에 저장할 수 있는지 궁금합니다.

현재 가지고 있는 코틀린 책도 없어서 구글링으로만 코드 작성 중이라 모르는 게 많습니다 ㅠㅠ..

안드로이드 코틀린 안드로이드스튜디오 firebase 파이어베이스
밈이 2021-05-04
밈이 님께서 2021-05-04에 Kotlin에 올린 질문

댓글

1개의 답변

0
addOnSuccessListener는 비동기로 실행됩니다. 즉, 언제 실행이 완료될 지 알 수 없는 코드입니다. 만약 중괄호 밖의 코드를 실행되기 전에 다행히 비동기 코드가 실행되었다면 정상적으로 동작하겠지만, 중괄호 밖의 코드가 실행될 때..

addOnSuccessListener는 비동기로 실행됩니다.

즉, 언제 실행이 완료될 지 알 수 없는 코드입니다.

만약 중괄호 밖의 코드를 실행되기 전에 다행히 비동기 코드가 실행되었다면 정상적으로 동작하겠지만,

중괄호 밖의 코드가 실행될 때 아직 비동기 코드가 실행되어있지 않으면 값을 가져오지 못해 오류가 발생할 수 있습니다.

다시 말해, 중괄호 밖의 코드는 비동기 코드가 완료된 후에 실행될 필요가 있습니다.

 

비동기 코드가 실행 완료되었는지 확인하고 이 후의 코드를 실행하도록 만드는 방법으로는

Coroutines를 사용하거나 Tasks를 사용하는 방법이 있습니다.

Coroutines를 사용하는 예,

private suspend fun getTokenResult (firebaseUser: FirebaseUser) = suspendCoroutine<GetTokenResult?> { continuation ->
firebaseUser.getIdToken(true).addOnCompleteListener {
    if (it.isSuccessful) {
        continuation.resume(it.result)
    } else {
        continuation.resume(null)
    }
}

Tasks의 await()를 사용하는 예,

object FcmToken {
    @JvmStatic
    fun getToken(): String? {
        val task = FirebaseInstanceId.getInstance().instanceId
        try {
            val result = Tasks.await(task)
            return result.token
        } catch (e: ExecutionException) {
            throw IllegalArgumentException("")
        } catch (e: InterruptedException) {
            throw IllegalArgumentException("")
        }
    }
}


...


viewModelScope.launch(Dispatchers.IO) {
    val result = FcmToken.getToken(viewModelScope)
    Log.e("result", result.toString())
}

 

무린 2021-05-06
사탕 주기
무린 님께서 2021-05-06에 Kotlin에 올린 글
보관하기

댓글

조회수 258
답글 1
URL