Reputation: 3016
I need to display a message each time an operation of adding/deleting an item in/from Firebase is complete. These are the functions in the interface:
suspend fun addItem(item: Item): Response<Unit>
suspend fun deleteItem(item: Item): Response<Unit>
These are the implementations:
override suspend fun addItem(item: Item) = try {
itemsRef.add(item).await()
Response.Success(Unit)
} catch (ex: Exception) {
Response.Failure(ex)
}
override suspend fun deleteItem(item: Item) = try {
itemsRef.document(item.id).delete().await()
Response.Success(Unit)
} catch (ex: Exception) {
Response.Failure(ex)
}
In the ViewModel I call the addItem
and reset the state of the operations like this:
class ItemViewModel @Inject constructor(
private val repo: ItemRepository
): ViewModel() {
private val _addItemResponse = MutableStateFlow<Response<String>?>(null)
val addItemResponse: StateFlow<Response<String>?> = _addItemResponse.asStateFlow()
private val _deleteItemResponse = MutableStateFlow<Response<String>?>(null)
val deleteItemResponse: StateFlow<Response<String>?> = _deleteItemResponse.asStateFlow()
fun addItem(item: Item) = viewModelScope.launch {
_addItemResponse.value = Response.Loading
_addItemResponse.value = repo.addItem(item)
}
fun deleteItem(item: Item) = viewModelScope.launch {
_deleteItemResponse.value = Response.Loading
_deleteItemResponse.value = repo.addItem(item)
}
fun resetAddItemState() = _addItemResponse.value?.let {
_addItemResponse.value = null
}
fun resetDeleteItemState() = _deleteItemResponse.value?.let {
_deleteItemResponse.value = null
}
}
And inside the UI I use:
when(val addItemResponse = viewModel.addItemResponse.collectAsStateWithLifecycle().value) {
is Response.Loading -> CircularProgressIndicator()
is Response.Success -> {
Toast.makeText(context, "Added", Toast.LENGTH_LONG).show()
resetAddItemState()
}
is Response.Failure -> Text(addItemResponse.ex)
}
when(val deleteItemResponse = viewModel.deleteItemResponse.collectAsStateWithLifecycle().value) {
is Response.Loading -> CircularProgressIndicator()
is Response.Success -> {
Toast.makeText(context, "Deleted", Toast.LENGTH_LONG).show()
resetDeleteItemState()
}
is Response.Failure -> Text(deleteItemResponse.ex)
}
When I add an item, the first toast is displayed. If I delete an item and wait for the second toast to disappear, the second toast is displayed correctly. However, if I add an item and delete it right away without waiting for the first toast to disappear, the second toast is not displayed. How to solve this issue?
Upvotes: 1
Views: 82
Reputation: 593
You can use a single Toast
instance and update its message. This ensures that the Toast
is displayed correctly without overlapping.
Here is the updated code:
class ItemActivity : AppCompatActivity() {
private lateinit var viewModel: ItemViewModel
private var toast: Toast? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_item)
viewModel = ViewModelProvider(this).get(ItemViewModel::class.java)
viewModel.addItemResponse.observe(this) { response ->
handleResponse(response, "Added")
}
viewModel.deleteItemResponse.observe(this) { response ->
handleResponse(response, "Deleted")
}
}
private fun handleResponse(response: Response<String>?, message: String) {
when (response) {
is Response.Loading -> {
// Show loading indicator if needed
}
is Response.Success -> {
showToast(message)
viewModel.resetAddItemState()
viewModel.resetDeleteItemState()
}
is Response.Failure -> {
showToast("Failed: ${response.ex.message}")
}
}
}
private fun showToast(message: String) {
toast?.cancel()
toast = Toast.makeText(this, message, Toast.LENGTH_LONG)
toast?.show()
}
}
Upvotes: 0
Reputation: 1
try to use applicationContext
Toast.makeText(applicationContext,"Message",Toast.LENGTH_SHORT).show()
Hope it will work.
Upvotes: 0