Retrofit断网时请求崩溃且无Logcat堆栈追踪的问题求助
Retrofit断网时请求崩溃且无Logcat堆栈追踪的问题求助
我是Android开发新手,最近在玩Retrofit+Jetpack Compose,在线状态下请求一切正常,但断网时请求会直接崩溃,而且我写的异常捕获没起作用,Logcat也没给出完整堆栈,只显示“fatal exception”。我已经在Manifest里加了INTERNET和ACCESS_NETWORK_STATE权限,实在搞不懂哪里出问题了,麻烦大家帮我看看!
我的代码如下:
@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)) } } } } }
兄弟,我一眼就看到问题所在了!你的try-catch范围完全错了!
你现在是先执行了RetrofitInstance.api.gettodo(),把结果赋值给todosresponse,之后才进入try块判断response的状态。但Retrofit的同步请求在断网这种场景下,调用gettodo()的时候就会直接抛出IOException,而这个调用根本不在你的try-catch包裹范围内,所以异常会直接逃逸导致崩溃,自然也不会被你的catch块捕获。
修复方案:把Retrofit的接口调用放到try块里面
把获取response的代码移到try块内部,这样网络异常才能被正常捕获,另外还要注意你代码里的一个小错误:isSuccessful()是错的,Retrofit的Response.isSuccessful是一个属性,不是方法,要去掉括号:
LaunchedEffect(Unit) { var todosresponse: Response<List<todos>>? = null val data = try { // 把接口调用移到try块里,这样网络异常会被捕获 todosresponse = RetrofitInstance.api.gettodo() if(todosresponse.isSuccessful && todosresponse.body() != null){ todos = todosresponse.body() ?: emptyList() Log.e("Api_CALL","Empty List") }else{ todos=emptyList() error="请求失败,请稍后重试" } } catch (e: IOException) { // 专门捕获网络相关异常,给用户更明确的提示 error = "网络连接失败,请检查网络" todos=emptyList() // 打印异常信息,方便自己调试 e.printStackTrace() } catch (e : Exception) { // 兜底处理其他异常 error="请求出错,请稍后重试" todos=emptyList() } finally { loading=false } }
额外建议:
- Logcat堆栈排查:你说Logcat没堆栈,可能是没开对过滤条件。可以在Logcat顶部选择“Error”级别,或者直接搜索“AndroidRuntime”,App崩溃的完整堆栈一般都会在这里输出。
- 用Retrofit协程风格接口:推荐给你的Retrofit接口加上
suspend修饰符,适配协程的异常处理逻辑会更顺畅:interface TodoApi { @GET("todos") suspend fun gettodo(): Response<List<todos>> } - 提前判断网络状态:虽然Retrofit会抛网络异常,但你也可以用
ConnectivityManager提前判断网络状态,给用户更及时的反馈,避免不必要的请求。
我之前也踩过这个try-catch范围的坑,把接口调用放到try块里就解决了,你试试看!
内容来源于stack exchange
相关产品推荐
相关产品推荐

