I. Introduction
Sealed Classes in Kotlin is a new concept that is not available in Java. Sealed Classes is an extension of traditional ENUM classes.
A sealed class allows you to represent constrained hierarchies in which an object can only be of one of the given types.
This means, we have a class with a specific number of subclasses. What we have is finally like an Enum. The difference is that in enum we only have one object per class, while with sealed classes we can have some objects of the same class. This difference helps to allow objects from a sealed class to hold the state.
II. Declaring Sealed classes
A sealed classes may have multiple subclasses, but all of them must be declared in the same file as the sealed sealed classes. For example:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | sealed class NetworkStatus { data class Loading(var loading: Boolean) : NetworkStatus() data class CustomSignal(var signal: String) : NetworkStatus() data class Failure(val e: Throwable) : NetworkStatus() companion object { fun loading(isLoading: Boolean): NetworkStatus = Loading(isLoading) fun customstatus(signal: String): NetworkStatus = CustomSignal(signal) fun failure(e: Throwable): NetworkStatus = Failure(e) } } |
The above code uses interface from view model to fragment
- Loading: To know when to start and end an Api call to show or hide progress
- CustomSignal: Use to send as Message or code
- Failure: Use to fire an error
III. Use sealed classes
Now that we know how to create sealed classes, it’s time to use it. As I mentioned, I used the sealed classes above to communicate from view model to fragment
To understand the details of using sealed classes, two things need to be understood:
- Where and how the data is updated
- Where and how data is used
1. Where and how is the data updated?
In this case I updated the livedata sealed classes in the viewmodel before and after calling the api, as follows:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 | private val livadataNetworkStatus = MutableLiveData<NetworkStatus>() fun getReviewsData(){ try { val call: Call<ReviewRespose>? = dependencyInstances.apiService?.getReviews(hashMap_daata) call?.enqueue(object : Callback< ReviewRespose> { override fun onFailure(call: Call< ReviewRespose>, t: Throwable) { val errorCaseData : ErrorCaseData = ErrorCaseData() errorCaseData.errorCode = 404 errorCaseData.message = t.message errorCaseData.retry = true errorCaseData.type = "Non Server" livadataLoading.postValue(NetworkStatus.customStatusDetailed(errorCaseData)) } override fun onResponse(call: Call< ReviewRespose>, response: Response< ReviewRespose>) { val it = response.body() it?.let { if (it.Error == null) { livadataLoading.postValue(NetworkStatus.loading(false)) } else { livadataLoading.postValue(NetworkStatus.customstatus(NetworkStatus.Error)) } } } }) } catch (e: Exception) { e.printStackTrace() livadataLoading.postValue(NetworkStatus.loading(false)) } } |
2. Where and how is data used?
Now we need to see how to use the data in the viewmodel:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | private fun setNetworkObserver() { viewModel?.getNetworkStatus()?.observe(this, Observer { activity?.let { act -> when (it) { is NetworkStatus.Loading -> { if (it.loading) { showLoading() } else { hideLoading() } } is NetworkStatus.CustomSignalDetailed -> { hideLoading() showErrorDialog(it.signal.message ?: getString(R.string.some_thing_wrong)) } is NetworkStatus.CustomSignal -> { hideLoading() setUpErrorView() } } } }) } |
IV. summary
Above is an introduction article about Sealed classes in Kotlin.
Thank you for reading.
ref: medium