I am trying to get user data from Firebase
Firestore
database ,
I am intended to get info of user who is currently logged in.
Now for make this information accessible from other Classes I created get method for username and email,
when I used get method from Another class , I got an indexOutOfBoundsException
with index 0,size 0.
It looks like my array in global scope is not getting data when i called array.add()
method from addOnSuccessListener
method.
package com.example.myapplication.utils
import android.os.Build
import androidx.annotation.RequiresApi
import com.example.myapplication.models.User
import com.google.firebase.auth.FirebaseAuth
import com.google.firebase.firestore.FirebaseFirestore
class UserInfo {
private val list = ArrayList<User>()
private val mFireStore = FirebaseFirestore.getInstance()
private fun getCurrentUserId(): String {
val currentUser = FirebaseAuth.getInstance().currentUser
var currentUserID = ""
if (currentUser != null) {
currentUserID = currentUser.uid
}
return currentUserID
}
@RequiresApi(Build.VERSION_CODES.R)
fun getUsername(): String {
getCurrentUser()
return list[0].userName
}
@RequiresApi(Build.VERSION_CODES.R)
fun getEmail(): String {
getCurrentUser()
return list[0].email
}
@RequiresApi(Build.VERSION_CODES.R)
private fun getCurrentUser() {
mFireStore.collection(Constants.USERS)
.document(getCurrentUserId())
.get()
.addOnSuccessListener { document ->
val user = document.toObject(User::class.java)
if (user != null) {
list.add(user)
}
}
.addOnFailureListener {
TODO()
}
}
}
CodePudding user response:
You can do this by using either callbackFlows
or RxJava
. I prefer callbackFlows
.
//This Needs to be a suspending function
private suspend fun getCurrentUser() = callbackFlow<User>{
firestore.collection(Constants.USERS)
.document(getCurrentUserId())
.get()
.addOnSuccessListener { document ->
val user = document.toObject(User::class.java)
if (user != null) {
list.add(user)
//Sends the data on cold Flow or Channel Flow
trySend(user)
}
}
.addOnFailureListener {
TODO()
}
awaitClose {
// suspends the current coroutine until the channel is either closed or canceled and invokes the given block before resuming the coroutine.
}
}
trySend
is where you send the data.
Also, awaitClose
is required.
Furthermore, from wherever you call this function, you need to collect
it, or else it won't work cold flows
require an active collector to work.
You can do this by simply,
private suspend fun collectCurrentUser() {
getCurrentUser().collect { data->
// Use Data
}
}
You can follow the following documentation: https://developer.android.com/kotlin/flow
CodePudding user response:
You can use Kotlin Unit function to return list
private fun getCurrentUser(listener:(ArrayList<User>())->Unit){
mFireStore.collection(Constants.USERS)
.document(getCurrentUserId())
.get()
.addOnSuccessListener { document ->
val user = document.toObject(User::class.java)
if (user != null) {
list.add(user)
}
listener.invoke(list)
}
.addOnFailureListener {
TODO()
}
}
Now you can this method as below
getCurrentUser(){list->
}