如何在Kotlin应用中每5秒向RPI请求数据且避免崩溃
解决方案:Kotlin定时请求RPI数据(无崩溃)
问题根源
你的第一个实现直接在UI线程中运行无限循环+Thread.sleep(5000),会彻底阻塞主线程,触发Android的ANR(应用无响应)机制,最终导致崩溃。服务端的循环方案无效,因为你的服务端是请求-响应模型,必须由客户端主动发起请求才会返回数据。
推荐实现:Kotlin协程(Android官方推荐)
协程是Kotlin中处理异步任务的优雅方案,既可以在后台执行网络请求,又能轻松控制定时任务的启停,不会阻塞UI线程。
步骤1:定义协程Job用于控制任务
在Activity/Fragment中声明一个Job变量,用来管理定时任务的生命周期:
private var fetchDataJob: Job? = null
步骤2:实现启动定时请求的函数
private fun startRealtimeFetch() { requestType = recentDataRequest // 更新UI状态 binding.periodDataButton.isVisible = true binding.realTimeDataButton.isVisible = false // 在IO调度器中执行网络请求,避免阻塞主线程 fetchDataJob = CoroutineScope(Dispatchers.IO).launch { // 用isActive判断任务是否已被取消,避免无效循环 while (isActive) { try { // 执行网络请求 communication.requette(requestType) // 切换回主线程更新UI withContext(Dispatchers.Main) { // 这里处理数据展示逻辑,比如更新对应UI控件 // 示例:binding.intensityText.text = recentData.intensity.toString() } } catch (e: Exception) { // 捕获网络异常,避免崩溃 e.printStackTrace() withContext(Dispatchers.Main) { Toast.makeText(this@YourActivity, "数据获取失败", Toast.LENGTH_SHORT).show() } } // 协程非阻塞延迟5秒,不会占用线程资源 delay(5000) } } }
步骤3:实现停止定时请求的函数
private fun stopRealtimeFetch() { // 取消协程任务,释放资源 fetchDataJob?.cancel() fetchDataJob = null // 恢复UI状态 binding.periodDataButton.isVisible = false binding.realTimeDataButton.isVisible = true }
步骤4:绑定按钮点击事件
在Activity的onCreate中设置按钮点击逻辑:
binding.realTimeDataButton.setOnClickListener { startRealtimeFetch() } binding.periodDataButton.setOnClickListener { stopRealtimeFetch() }
关键优势
- 非阻塞:
delay(5000)是协程的非阻塞延迟,不会像Thread.sleep那样占用线程资源。 - 线程安全:网络请求在IO线程执行,UI更新切换回主线程,符合Android线程规范。
- 可控制:通过
Job对象可以随时取消任务,避免Activity/Fragment销毁后仍运行导致内存泄漏。 - 异常安全:捕获网络异常,防止请求失败直接崩溃。
内容的提问来源于stack exchange,提问作者Oscar Pill
相关产品推荐
相关产品推荐

