I'm trying to display an error message to the users when something went wrong with a Retrofit API call. I'm using Kotlin Coroutines, Kodein and MVVM pattern. I have trouble displaying the error message in a toast message given that the MutableLiveData exceptionMessage is not really observed in the fragment (I'm guessing this has something to do with the nature of the asynchronous function to get the data via the API (suspend fun)).
ViewModel:
class BarcodeViewModel(
private val barcodeRepository: BarcodeRepository,
private val productRepository: ProductRepository
) : ViewModel() {
var exceptionMessage: MutableLiveData<String> = MutableLiveData()
private val handler = CoroutineExceptionHandler { _, exception ->
exceptionMessage.value = exception.localizedMessage
}
fun getBarcodeData(barcode: String) {
CoroutineScope(Dispatchers.Main).launch(handler) {
val currentArticle = barcodeRepository.getProductData(barcode)
for (article in currentArticle.products) {
val articleToAdd =
Product(...)
val articleDb = productRepository.getProduct(barcode)
if (articleDb.isEmpty()) {
productRepository.addProduct(articleToAdd)
exceptionMessage.value = ""
} else {
exceptionMessage.value = "Product already exists"
}
}
}
}
}
Fragment:
class ArticleAddFragment : Fragment(), LifecycleOwner, KodeinAware {
override val kodein: Kodein by kodein()
private val factory: BarcodeViewModelFactory by instance()
private lateinit var viewModel: BarcodeViewModel
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
val view = inflater.inflate(R.layout.fragment_article_add, container, false)
viewModel = ViewModelProviders.of(this, factory).get(BarcodeViewModel::class.java)
...
return view
}
private fun processResult(firebaseVisionBarcodes: List<FirebaseVisionBarcode>) {
if (firebaseVisionBarcodes.isNotEmpty()) {
for (item in firebaseVisionBarcodes) {
when (item.valueType) {
FirebaseVisionBarcode.TYPE_PRODUCT -> {
viewModel.getBarcodeData(item.rawValue!!)
viewModel.exceptionMessage.observe(viewLifecycleOwner, Observer {
it?.let {
if (!it.isBlank()) {
Toast.makeText(context, it, Toast.LENGTH_SHORT).show()
}
}
})
...
}
}
}
}
}
What's the smartest way to display the error message in a toast?