개발노트/Kotlin

파이널 프로젝트 2주차 2일

시계속세상은아직돌아가는중 2023. 10. 17. 21:51

1. firebase의 비동기 실행

 

원인코드

    override fun getData(): LiveData<List<FireModel>> {

        val resultLiveData = MutableLiveData<List<FireModel>>()

        val database = Firebase.database
        val myRef = database.getReference("borad1")

        myRef.addValueEventListener(object : ValueEventListener {
            override fun onDataChange(snapshot: DataSnapshot) {

                val dataList = mutableListOf<FireModel>()

                if (snapshot.exists()) {
                    for (userSnapshot in snapshot.children) {
                        val itemKey = userSnapshot.key ?: ""
                        val getData = userSnapshot.getValue(Model::class.java)

                        getData?.let {
                            val fireModel = FireModel(itemKey, it.title)
                            dataList.add(fireModel)
                        }
                    }

                    resultLiveData.postValue(dataList)
                }
            }

            override fun onCancelled(error: DatabaseError) {
                TODO("Not yet implemented")
            }

        })

        return resultLiveData
    }

listner 부분이 비동기 실행이 되는 문제였다.

return을 그 밖에서 해주니 아무리 실행해도 null값이 먼저 리턴이 된 뒤 비동기로 완료된 값이 받아졌다.

 

이를 해결하기 위한 코루틴을 사용한 코드

 

    override suspend fun getDataFromTemplate(template: String, user: String): List<FireModel> {
        val database = Firebase.database

        try {
            val snapshot = database.getReference("$user/$template/title").get().await()
            Log.d("템플릿.repo", "$user/$template/title")

            if (snapshot.exists()) {
                val dataList = mutableListOf<FireModel>()

                for (userSnapshot in snapshot.children) {
                    val itemKey = userSnapshot.key ?: ""
                    val getData = userSnapshot.getValue(Model::class.java)

                    getData?.let { model ->

                        val fireModel =
                            FireModel(
                                key = itemKey,
                                title = model.title
                            )

                        dataList.add(fireModel)
                    }
                }
                return dataList
            } else {
                return emptyList()
            }
        } catch (e: Exception) {
            // 여기서 예외 처리 코드를 작성합니다.
            Log.e("템플릿.repo", "데이터 가져오기 중 오류 발생: ${e.message}")
            return emptyList() // 또는 예외 처리에 따른 적절한 반환 값 설정
        }
    }

는 문제가 있다면 onCancelled가 없기 때문에 에러 케이스에 캐치가 어렵다.

때문에 try-catch문을 이용하여 에러 발생시 에러 로그가 남고 빈 list를 반환하도록 설계하였다.

 

또한 livedata return이 아닌 list return이기 때문에 각 메소드들이 실행될 때 마다 최신으로 업데이트 하도록 해주었다.

 

2. 액티비티에서 최신화

 

프래그먼트는 화면 밖으로 나가면 destroy 즉 종료되기 때문에 데이터를 알아서 갱신해준다.

하지만 테스트 코드는 activity로 만들어줬기 때문에 resume단계에서 데이터를 갱신해줄 필요가 있었다.

 

  override fun onResume() {
        super.onResume()

        updateResume(currentTemplate)
    }

 

액티비티의 생명주기를 잊지 말자!

 

 

 

 

참고 사이트

https://joebirch.co/android/using-firebase-on-android-with-kotlin-coroutines/

 

Using Firebase on Android with Kotlin Coroutines

Whilst recently working on a side project I ran into a situation where I needed to make use of the Android Firebase SDKs. This project of mine uses Kotlin Coroutines for all of the asynchronous task handling, so ideally I wanted to keep any Firebase calls

joebirch.co