I am totally new to sealed Interface
in Kotlin. I am trying to state management through sealed
in Android Kotlin. My main goal is when
I use the object of sealed
I don't want to inherit all children. I am not sure if sealed interface
is the right choice for me. All my code may be wrong, please correct me if I am wrong. Thanks.
sealed interface ConnectionUIState
sealed class BluetoothConnectionUIState {
object Initial : BluetoothConnectionUIState()
data class ScanningDevice(val storedDevice: SnapshotStateList<BluetoothDevice>? = null) : ConnectionUIState
}
I initialise the variable like this:
var uiState by mutableStateOf<BluetoothConnectionUIState>(BluetoothConnectionUIState.Initial)
private set
Now I am passing the uiState
variable in the function and using when
statement:
when (uiState) {
BluetoothConnectionUIState.ScanningDevice -> {
xuz()
}
}
why when
statement is giving error:
'when' expression must be exhaustive, add necessary 'Initial' branch or 'else' branch instead
Also this line is also giving me error: BluetoothConnectionUIState.ScanningDevice
in when
statement.
Error
Classifier 'ScanningDevice' does not have a companion object, and thus must be initialized here
If I am doing wrong here. Can you please elaborate of 2 point of this stack overflow. Thanks.
UPDATE
I did some changes:
sealed interface ConnectionUIState
sealed class BluetoothConnectionUIState {
object Initial : ConnectionUIState
data class ScanningDevice(val storedDevice: SnapshotStateList<BluetoothDevice>? = null) : BluetoothConnectionUIState()
}
I did success on when
statement that it's not complaining about Initial
:
when (uiState) {
is BluetoothConnectionUIState.ScanningDevice -> {
BluetoothPairContent(viewModel, tryAgainAction, openSettingAction, scanDeviceList)
}
}
That is my goal, but another problem raised that it gives error in uiState
initialise time:
var uiState by mutableStateOf<BluetoothConnectionUIState>(BluetoothConnectionUIState.Initial)
private set
**Error**
Type mismatch.
Required:
BluetoothConnectionUIState
Found:
BluetoothConnectionUIState.Initial
Again I am confused. Please guide me on this. Thanks
(I think you worked it out but just in case - you need is
in your when
to check if something is
a class. When comparing to an object
you use equality, which can just be written as the value to match)
Working off your update:
// simplified for readability
sealed interface ConnectionUIState
sealed class BluetoothConnectionUIState {
object Initial : ConnectionUIState
data class ScanningDevice : BluetoothConnectionUIState()
}
You've got this object and class nested inside BluetoothConnectionUIState
, which means their fully qualified names are things like BluetoothConnectionUIState.Initial
. But you don't actually have to nest them, you can do this:
sealed class BluetoothConnectionUIState
object Initial : ConnectionUIState
data class ScanningDevice : BluetoothConnectionUIState()
Now Initial
and ScanningDevice
aren't nested inside BluetoothConnectionUIState
, you just reference them directly. So what's the relationship between them now? Look at the constructors:
// subclass of BluetoothConnectionUIState
data class ScanningDevice : BluetoothConnectionUIState()
// implements the ConnectionUIState interface
object Initial : ConnectionUIState
Once you remove the nesting, you can see that Initial
actually has no type relationship with the sealed class at all! It just happened to be located inside it. And that's why you can't put it in your mutableStateOf
- it's not a BluetoothConnectionUIState.
It's also why you were getting the must be exhaustive error in your original when
block - you only had a branch checking Initial
, which isn't part of the sealed class anyway. It works when you check ScanningDevice
, because that's the only member of the class - if uiState
is a BluetoothConnectionUIState
, it must be a ScanningDevice
.
How you fix this is up to you - seems like you want those two things to be part of the same sealed class. Maybe you want ConnectionUIState
to be the sealed class? Since that's what they both represent. And have BluetoothConnectionUIState
be the interface that you can apply selectively to certain members of that sealed class?
sealed interface BluetoothConnectionUIState
sealed class ConnectionUIState {
object Initial : ConnectionUIState()
data class ScanningDevice : ConnectionUIState(), BluetoothConnectionUIState
}