androidkotlin

App crashes when internet is turned off but works fine when internet is on and no logcat stack trace


I have already looked up some previous questions here in stack overflow but have not found suitable answers for this issue i am new to android dev so i was like playing around with retrofit and as i stated it works fine when i am online however when i turn internet off the query fails and the app crashes (it is not caught in the exception which i have implemented) and logcat does not give me a stack trace to debug (there are no filters in logcat) it simply says fatal exception

this is the code :

@Composable
fun api_call_screen(navController: NavController){

    var todos by rememberSaveable { mutableStateOf<List<todos>>(emptyList()) }
    var loading by rememberSaveable { mutableStateOf<Boolean>(true) }
    var error by rememberSaveable { mutableStateOf<String?>(null) }

    LaunchedEffect(Unit) {
        val todosresponse =RetrofitInstance.api.gettodo()

        val data =try {
            if(todosresponse.isSuccessful() && todosresponse.body() != null){
                todos =todosresponse.body() ?: emptyList()
                Log.e("Api_CALL","Empty List")
            }else{
                todos=emptyList()
                error="Something went wrong"
            }
        }
        catch (e : Exception){

             error="Something went wrong"
             todos=emptyList()

        }
        finally {
            loading=false

        }
    }
    Box(modifier = Modifier.fillMaxSize()){
        if(loading){
            CircularProgressIndicator(modifier = Modifier.align(Alignment.Center))
        }else if(error !=null){
            Text("$error", modifier = Modifier.align(Alignment.Center))
        }
        else if (todos==emptyList<todos>()){
            Text("No Data", modifier = Modifier.align(Alignment.Center))
        }
        else{
            LazyColumn {
                items(items = todos){
                    todo ->Text(todo.title, modifier = Modifier.padding(16.dp))
                }
            }
        }
    }

}

i have not implemented any network checks since i have read the docs and have seen that a IOException would be thrown just confused why it si not caught is there some other error that is happening outside the scope that is caught ? i have no idea kindly help me figure it out and thanks in advance :)

i have also setup the necessary permissions in android manifest file :

    <uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>

The Logcat view : enter image description here


Solution

  • You need to wrap the entire Retrofit call inside the try-catch. Retrofit throws IOException when the device is offline or the server is unreachable.

    LaunchedEffect(Unit) {
        try {
            val todosresponse = RetrofitInstance.api.gettodo()
    
            if (todosresponse.isSuccessful && todosresponse.body() != null) {
                todos = todosresponse.body() ?: emptyList()
                Log.e("Api_CALL", "Got data")
            } else {
                todos = emptyList()
                error = "Server Error: ${todosresponse.code()}"
            }
        } catch (e: IOException) {
            // Network error like no internet
            error = "No internet connection."
            todos = emptyList()
            Log.e("NetworkError", "IOException: ${e.localizedMessage}")
        } catch (e: Exception) {
            // Other unexpected errors
            error = "Unexpected error occurred."
            todos = emptyList()
            Log.e("UnknownError", "Exception: ${e.localizedMessage}")
        } finally {
            loading = false
        }
    }
    

    and

    Don’t compare lists like if (todos == emptyList<todos>())

    Instead, use .isEmpty():

    else if (todos.isEmpty())
    {
        Text("No Data", modifier = Modifier.align(Alignment.Center))
    }