MainActivity
class MainActivity : AppCompatActivity() {
lateinit var viewModel: ListViewModel
private val countriesAdapter = CountryListAdapter(arrayListOf())
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
viewModel = ViewModelProviders.of(this).get(ListViewModel::class.java)
viewModel.refresh()
countriesList.apply {
layoutManager = LinearLayoutManager(context)
adapter = countriesAdapter
}
observeViewModel()
}
fun observeViewModel() {
viewModel.countries.observe(this, Observer {countries ->
countries?.let {
countriesList.visibility = View.VISIBLE
countriesAdapter.updateCountries(it) }
})
viewModel.countryLoadError.observe(this, Observer { isError ->
list_error.visibility = if(isError == "") View.GONE else View.VISIBLE
})
viewModel.loading.observe(this, Observer { isLoading ->
isLoading?.let {
loading_view.visibility = if(it) View.VISIBLE else View.GONE
if(it) {
list_error.visibility = View.GONE
countriesList.visibility = View.GONE
}
}
})
}
}ViewModel
class ListViewModel: ViewModel() {
val countriesService = CountriesService.getCountriesService()
var job: Job? = null
val exceptionHandler = CoroutineExceptionHandler { coroutineContext, throwable ->
onError("Exception: ${throwable.localizedMessage}")
}
val countries = MutableLiveData<List<Country>>()
val countryLoadError = MutableLiveData<String?>()
val loading = MutableLiveData<Boolean>()
fun refresh() {
fetchCountries()
}
private fun fetchCountries() {
loading.value = true
job = CoroutineScope(Dispatchers.IO + exceptionHandler).launch {
val response = countriesService.getCountries()
withContext(Dispatchers.Main) {
if(response.isSuccessful) {
countries.value = response.body()
countryLoadError.value = null
loading.value = false
} else {
onError("Error: ${response.message()}")
}
}
}
}
private fun onError(message: String) {
countryLoadError.value = message
loading.value = false
}
override fun onCleared() {
super.onCleared()
job?.cancel()
}
}