Mehul Kanzariya
Mehul Kanzariya

Reputation: 1348

Error in using Firestore with Android Architecture Components

I have an activity where a User is made to log in. Once the User logs in, the User detail is uploaded to the Firebase which is observed using the LiveData in the activity.

The problem is even though the data is successfully uploaded, the LiveData is showing that an error occurred.

Activity

class LoginActivity : AppCompatActivity() {

private val RC_SIGN_IN = 123

private val viewModel by viewModel<LoginViewModel>() // Lazy inject ViewModel

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_login)
    loginUser()
    observeLoginLiveData()
}


private fun observeLoginLiveData() {
    viewModel.onAuthenticationSuccessful().observe(this, Observer { result ->
        when (result) {
            is Result.Loading -> {
            }

            is Result.Success<*> -> {
                startActivity(Intent(this, MainActivity::class.java))
                finish()
            }

            is Result.Error -> {
                clLogin.showSnackbar(R.string.error_login) {}
                Timber.e(result.errorMessage)
            }
        }
    })
 }
}

ViewModel

class LoginViewModel(val repo: LoginRepository) : ViewModel() {

private val _loginLiveData = MutableLiveData<Result>()
private val loginLiveData: LiveData<Result>
    get() = _loginLiveData

fun onAuthenticationSuccessful(): LiveData<Result> {
    _loginLiveData.value = Result.Loading
    viewModelScope.launch {
        _loginLiveData.value = repo.uploadUserDetails()
    }
    return loginLiveData
 }
}

Repository

class LoginRepository {

suspend fun uploadUserDetails(): Result {
val response = withContext(Dispatchers.IO) {
        val currentUser = FirebaseUtils.getCurrentUser()
        val user = User(currentUser?.displayName, currentUser?.email, currentUser?.photoUrl.toString())

        FirebaseFirestore.getInstance()
            .collection(FirebaseReferences.COLLECTION_USERS)
            .add(user)
    }

    return if (response.isSuccessful) {
        Result.Success("true")
    } else {
        Result.Error("Error uploading user data")
    }
 }
}

I have also tried using response.isComplete but it also returns false everytime.

I don't know what I am missing here. Any help will be appreciated. Thanks.

Upvotes: 0

Views: 170

Answers (1)

Mehul Kanzariya
Mehul Kanzariya

Reputation: 1348

As suggested in the comment, I changed the code to wait for the result as shown below and now I am getting the proper response:

Changed ViewModel

class LoginViewModel(val repo: LoginRepository) : ViewModel() {

private val _loginLiveData = MutableLiveData<Result>()
private val loginLiveData: LiveData<Result>
    get() = _loginLiveData

fun onAuthenticationSuccessful(): LiveData<Result> {
    _loginLiveData.value = Result.Loading

    viewModelScope.launch {
        repo.uploadUserDetails().addOnCompleteListener {
            if (it.isSuccessful) {
                _loginLiveData.value = Result.Success("true")
            } else {
                _loginLiveData.value = Result.Error("Error uploading user data")
            }
        }
    }
    return loginLiveData
 }
}

Changed Repository

class LoginRepository {

suspend fun uploadUserDetails(): Task<DocumentReference> = withContext(Dispatchers.IO) {
    val currentUser = FirebaseUtils.getCurrentUser()
    val user = User(currentUser?.displayName, currentUser?.email, currentUser?.photoUrl.toString())

    FirebaseFirestore.getInstance()
        .collection(FirebaseReferences.COLLECTION_USERS)
        .add(user)
 }
}

Upvotes: 1

Related Questions