This capstone ties together every module: Retrofit for a movie API, Room for offline caching, a Repository unifying both, a ViewModel exposing sealed-class UI state, and a ListAdapter with DiffUtil displaying results.
class MovieViewModel(private val repository: MovieRepository) : ViewModel() {
private val _uiState = MutableLiveData<NetworkResult<List<Movie>>>()
val uiState: LiveData<NetworkResult<List<Movie>>> = _uiState
fun loadPopularMovies() {
_uiState.value = NetworkResult.Loading
viewModelScope.launch {
_uiState.value = repository.getPopularMovies()
}
}
}
viewModel.uiState.observe(viewLifecycleOwner) { state ->
when (state) {
is NetworkResult.Loading -> binding.progressBar.isVisible = true
is NetworkResult.Success -> {
binding.progressBar.isVisible = false
movieAdapter.submitList(state.data)
}
is NetworkResult.Error -> {
binding.progressBar.isVisible = false
Snackbar.make(binding.root, state.message, Snackbar.LENGTH_LONG).show()
}
}
}
This is the shape of a genuinely production-style Android screen — every layer from Module 1 through Module 5 is represented here.
- Image
- SKU
- Rating
- Price
- Stock
- Availability
- Add to cart
- Description
- Content
- Weight
- Dimensions
- Additional information