androidkotlinandroid-jetpack-composetry-catchsqliteexception

How can I call try/catch in a Composable Button


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.


Solution

  • 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
            }
     }