Reputation: 4712
I want to check if my database write was successful in order to show the user an error message.
My current approach doesn't work as it says "Type mismatch, required Unit found EmailStatus"
class EmailRepositoryImpl : EmailRepository {
private val db = Firebase.firestore
override fun sendEmail(email: Email): EmailStatus<Nothing> {
db.collection("emails").document().set(email).addOnCompleteListener {
if (it.isSuccessful) return@addOnCompleteListener EmailStatus.Success<Nothing>
if (it.isCanceled) return@addOnCompleteListener EmailStatus.Error(it.exception!!)
}
}
}
sealed class EmailStatus<out T> {
data class Success<out T>(val data: T) : EmailStatus<T>()
data class Error(val exception: Exception) : EmailStatus<Nothing>()
}
Is it even possible to write something like this? As far as I know there is a generic firebase error type
but I didn't found anything related to kotlin or android...
I appreciate every help, thank you
I've tried getting my document, but I am just getting null: (When I use the listener approach, everything works fine)
interface EmailRepository {
suspend fun getEmail(): Flow<EmailEntity?>
}
override suspend fun getEmail(): Flow<EmailEntity?> = flow {
val result = db.collection("emailprice").document("Email").get().await()
emit(result.toObject<EmailEntity>())
}
private val emailEntity = liveData<EmailEntity?>(Dispatchers.IO) {
emailRepository.getCalibratePrice()
}
Upvotes: 0
Views: 1580
Reputation: 13129
The problem is that addOnCompleteListener
callback does not return anything (Unit) and you are trying to return an EmailStatus
from that scope.
You have three approaches:
I think the easiest way to do this one shot operation is to use Coroutines; I have written an article about that.
Upvotes: 2
Reputation: 4712
Okay, this is the final solution, thanks to @Gastón Saillén and @Doug Stevenson :
interface EmailRepository {
fun sendEmail(email: Email): Flow<EmailStatus<Unit>>
}
class EmailRepositoryImpl @Inject constructor(
private val db: FirebaseFirestore
) : EmailRepository {
override fun sendEmail(email: Email)= flow<EmailStatus<Unit>> {
db.collection("emails").add(email).await()
emit(EmailStatus.success(Unit))
}.catch {
emit(EmailStatus.failed(it.message.toString()))
}.flowOn(Dispatchers.Main)
}
fun sendEmail(): LiveData<EmailStatus<Unit>> {
val newEmail = createEmail()
return emailRepository.sendEmail(newEmail).asLiveData()
}
btn.setOnClickListener {
viewModel.sendEmail().observe(viewLifecycleOwner) {
when(it) {
is EmailStatus.Success -> {
valid = true
navigateTo(next, bundleNext)
Toast.makeText(requireContext(), "Success", Toast.LENGTH_SHORT).show()
}
is EmailStatus.Failure -> {
valid = false
Toast.makeText(requireContext(), "Failed ${it.message}", Toast.LENGTH_SHORT).show()
}
}
}
}
The only problem I currently have is that my "faield state" does not work like it should.
It should fail, if the user has no internet access. Currently, the write to the db never fails and Firebase just waits till the user has internet access. The problem here is that when I click multiple times, the write is executed multiple times. But I think I have to implement a bit more logic here and the above written code is fine like it currently is.
Upvotes: 0