Nur eine Implementierung der Methode aus Chris Cooks Antwort:
Zuerst benötigen wir das Objekt, das Antwortdaten und Ausnahmen enthält:
data class Resource<out T>(val status: Status, val data: T?, val exception: Throwable?) {
enum class Status {
LOADING,
SUCCESS,
ERROR,
}
companion object {
fun <T> success(data: T?): Resource<T> {
return Resource(Status.SUCCESS, data, null)
}
fun <T> error(exception: Throwable): Resource<T> {
return Resource(Status.ERROR, null, exception)
}
fun <T> loading(): Resource<T> {
return Resource(Status.LOADING, null, null)
}
}
}
Und dann meine eigene Erfindung - AsyncExecutor .
Diese kleine Klasse macht 3 wichtige Dinge:
- Gibt ein praktisches Standard-LiveData-Objekt zurück.
- Anruf bereitgestellt Rückruf asynchron.
- Nimmt das Ergebnis des Rückrufs oder fängt eine Ausnahme ab und fügt sie in die LiveData ein.
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
class AsyncExecutor {
companion object {
fun <T> run(callback: () -> T): LiveData<Resource<T>> {
val resourceData: MutableLiveData<Resource<T>> = MutableLiveData()
Thread(Runnable {
try {
resourceData.postValue(Resource.loading())
val callResult: T = callback()
resourceData.postValue(Resource.success(callResult))
} catch (e: Throwable) {
resourceData.postValue(Resource.error(e))
}
}).start()
return resourceData
}
}
}
Anschließend können Sie in Ihrem ViewModel LiveData erstellen, die das Ergebnis Ihres Rückrufs oder Ihrer Ausnahme enthalten:
class GalleryViewModel : ViewModel() {
val myData: LiveData<Resource<MyData>>
init {
myData = AsyncExecutor.run {
return MyData()
}
}
}
Und dann können Sie Ihre Daten und alle Ausnahmen in der Benutzeroberfläche abrufen:
class GalleryFragment : Fragment() {
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
galleryViewModel = ViewModelProviders.of(this).get(GalleryViewModel::class.java)
galleryViewModel.myData.observe(viewLifecycleOwner, Observer {
when {
it.status === Resource.Status.LOADING -> {
println("Data is loading...")
}
it.status === Resource.Status.ERROR -> {
it.exception!!.printStackTrace()
}
it.status === Resource.Status.SUCCESS -> {
println("Data has been received: " + it.data!!.someField)
}
}
})
return root
}
}