I need to catch a SQLiteException in a Composable Button click event. I am executing a Room function to Insert a record. It has a Unique constraint field/index.
I found the following code.
And found Stackoverflow link
I tried the accepted option and the third option, but did not work.
Here is my code:
ADO ///////
interface houseDAO {
@Insert(onConflict = OnConflictStrategy.ABORT )
@Throws(SQLiteException::class)
suspend fun addHouse(houseEntity: HouseEntity)
//More DAO functions
}
Repository ////////
class InventoryRepository (val inventoryDB: InventoryDB){
suspend fun addhouseToRoom(houseEntity: HouseEntity){
inventoryDB.houseDao().addHouse(houseEntity)
}
//More functions
}
Viewmodel //////////
class InventoryViewModel(val repository: InventoryRepository): ViewModel() {
fun addhouse(house: HouseEntity) {
viewModelScope.launch {
repository.addhouseToRoom(house)
}
}
//More functions
}
Composable function ///////////
//More functions
Column(
modifier = Modifier
.padding(top = 22.dp, start = 6.dp, end = 6.dp)
.fillMaxWidth(),
horizontalAlignment = Alignment.CenterHorizontally
) {
val coroutineScope = rememberCoroutineScope()
//Commented line because the addfloor function does not returns any value
//val (loadResult, setLoadResult) = remember { mutableStateOf<String?>(null) }
Button(
onClick = {
coroutineScope.launch {
withContext(Dispatchers.IO) {
try {
viewModel.addfloor(
FloorEntity(
0,
houseId!!.toLong(),
infloor,
"$location.$infloor"
)
)
mToast("Floor Added", mContext)
} catch (e: SQLiteException) {
msgbox(
mContext,
e.message.toString(),
"Floor Could not be Added"
)
}
}
}
},
colors = ButtonDefaults.buttonColors(Color.Blue)
) {
Text(text = "Add Floor in to House")
}
}
//More functions
The error is catched in another place on the application where I have a catch all errors segment.
Improved Answer:
ViewModel ///////
Instead of doing the message directly in the ViewModel emit a code and catch it in the the Composable.
fun addroom(room: RoomEntity) {
viewModelScope.launch {
try {
repository.addroomToRoom(room)
_errorR.emit(0)
//msgbox(mContext, "", "Room Added")
} catch (e: SQLiteException) {
_errorR.emit(-2)
_errorRe.emit(e.message.toString())
//msgbox(mContext, errorparse(e.message.toString(),"Name"), "Room Could not be Added")
}
}
}
Composable function /////
Catch the ViewModel emitted code and do a LaunchedEffect with the message.
Button(
enable = benabled,
onClick = {
viewModel.addroom(mContext,
RoomEntity(
0,
floorId!!.toLong(),
inroomname,
inroomtype.value,
"$location.$inroomname"
)
)
//mToast("Room Added", mContext)
},
colors = ButtonDefaults.buttonColors(Color.Blue)
) {
Text(text = "Add Romm into Floor")
}
val errorR by viewModel.errorR.collectAsStateWithLifecycle()
val error by viewModel.errorRe.collectAsStateWithLifecycle()
LaunchedEffect(errorR) {
if (errorR == -1) return@LaunchedEffect
if (errorR == 0) {
viewModel.seterrorR()
msgbox(mContext, "", "Room Added")
navController.popBackStack()
}
}
LaunchedEffect(error) {
if (error == "") return@LaunchedEffect
else {
viewModel.seterrorRe()
msgbox(
mContext,
errorparse(viewModel, error, "Name"), "Room could not be Added"
)
benabled = true
}
}