Firebase:如何检查文档写入是否成功
Firebase: How to check if document write was successful
我想检查我的数据库写入是否成功,以便向用户显示错误消息。
我目前的方法不起作用,因为它说“类型不匹配,需要的单位找到 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!!)
}
}
}
状态密封Class
sealed class EmailStatus<out T> {
data class Success<out T>(val data: T) : EmailStatus<T>()
data class Error(val exception: Exception) : EmailStatus<Nothing>()
}
甚至可以写这样的东西吗?据我所知,有一个通用的 firebase error type
但我没有发现任何与 kotlin 或 android...
相关的内容
非常感谢您的帮助,谢谢
编辑
我已经尝试获取我的文档,但我只是得到空值:(当我使用侦听器方法时,一切正常)
界面
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()
}
问题是 addOnCompleteListener
回调没有 return 任何东西(单位),而您正在尝试从该范围 return 一个 EmailStatus
。
你有三种方法:
- 创建一个将填充值的接口,return 将 EmailStatus 向下填充到您的调用层
- 当对 firebase 的异步调用完成后,使用协程暂停此函数,然后return那个值
- 在数据准备好处理时使用 Flow 提供数据
我认为完成这种一次性操作的最简单方法是使用协程;我写了an article about that.
好的,这是最终的解决方案,感谢@Gastón Saillén 和@Doug Stevenson:
电子邮件存储库
interface EmailRepository {
fun sendEmail(email: Email): Flow<EmailStatus<Unit>>
}
EmailRepository 实现
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()
}
}
}
}
我目前遇到的唯一问题是我的“失败状态”无法正常工作。
如果用户无法访问互联网,它应该会失败。目前,写入数据库永远不会失败,Firebase 只会等待用户访问互联网。这里的问题是,当我多次点击时,写入被执行了多次。但我想我必须在这里实现更多的逻辑,上面编写的代码和现在一样没问题。
我想检查我的数据库写入是否成功,以便向用户显示错误消息。
我目前的方法不起作用,因为它说“类型不匹配,需要的单位找到 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!!)
}
}
}
状态密封Class
sealed class EmailStatus<out T> {
data class Success<out T>(val data: T) : EmailStatus<T>()
data class Error(val exception: Exception) : EmailStatus<Nothing>()
}
甚至可以写这样的东西吗?据我所知,有一个通用的 firebase error type
但我没有发现任何与 kotlin 或 android...
非常感谢您的帮助,谢谢
编辑
我已经尝试获取我的文档,但我只是得到空值:(当我使用侦听器方法时,一切正常)
界面
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()
}
问题是 addOnCompleteListener
回调没有 return 任何东西(单位),而您正在尝试从该范围 return 一个 EmailStatus
。
你有三种方法:
- 创建一个将填充值的接口,return 将 EmailStatus 向下填充到您的调用层
- 当对 firebase 的异步调用完成后,使用协程暂停此函数,然后return那个值
- 在数据准备好处理时使用 Flow 提供数据
我认为完成这种一次性操作的最简单方法是使用协程;我写了an article about that.
好的,这是最终的解决方案,感谢@Gastón Saillén 和@Doug Stevenson:
电子邮件存储库
interface EmailRepository {
fun sendEmail(email: Email): Flow<EmailStatus<Unit>>
}
EmailRepository 实现
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()
}
}
}
}
我目前遇到的唯一问题是我的“失败状态”无法正常工作。
如果用户无法访问互联网,它应该会失败。目前,写入数据库永远不会失败,Firebase 只会等待用户访问互联网。这里的问题是,当我多次点击时,写入被执行了多次。但我想我必须在这里实现更多的逻辑,上面编写的代码和现在一样没问题。