求助:startActivity调用与目标Activity的onCreate启动存在超20秒延迟
问题分析与解决方案
核心问题拆解
你遇到两个关联问题:
- 调用
startActivity()后,GameActivity的onCreate()启动延迟超20秒 - 等待对话框
waitDialog无法正常显示
问题1:WaitDialog不显示的直接原因
你的代码逻辑存在两个致命问题:
- 耗时操作(图片处理、ML预测)在主线程执行,阻塞UI消息循环,导致对话框的绘制请求无法被及时处理
finally块里的waitDialog.dismiss()会在耗时操作启动后立即执行,对话框刚调用show()就被关闭,根本来不及显示
问题2:Activity启动延迟的核心原因
主线程被耗时操作阻塞是关键:Android的Activity启动依赖主线程的消息循环调度,当CameraActivity的主线程被图片处理、ML预测占用时,系统无法及时响应startActivity()的请求,导致GameActivity的启动被大幅延迟。
具体修复方案
1. 重构耗时操作到后台线程,修复Dialog显示
将图片处理、ML预测逻辑移到IO线程执行,仅在主线程处理UI操作(显示/关闭Dialog、启动Activity):
private fun takePicture() { waitDialog = MyDialogFragment(getString(R.string.wait), false, this) waitDialog.show(supportFragmentManager, "wait_dialog") // 用生命周期协程在后台执行耗时任务 lifecycleScope.launch(Dispatchers.IO) { try { val time1 = ZonedDateTime.now() // 耗时操作移到IO线程 val cellGrid = ImageProcessing.getCellGrid(currentImage) val puzzle = Puzzle(MLUtilities.predictPuzzle(cellGrid)) val intent = Intent(this@CameraActivity, GameActivity::class.java) intent.putExtra("case", Case.CAMERA.toString()) intent.putExtra("stage", Stage.INPUT.toString()) // 优化数据传递:避免81次putExtra(后面会详细说) repeat(9) { i -> repeat(9) { j -> intent.putExtra("value$i$j", puzzle.get(i, j)) } } val time2 = ZonedDateTime.now() // 回到主线程执行UI操作 withContext(Dispatchers.Main) { CameraActivity.time1 = time1 CameraActivity.time2 = time2 startActivity(intent) } } catch (e: Exception) { Log.e(MainActivity.TAG, "", e) } finally { // 主线程关闭对话框 withContext(Dispatchers.Main) { if (waitDialog.isAdded && !waitDialog.isDetached) { waitDialog.dismiss() } } } } }
2. 优化Intent数据传递,减少启动开销
当前用81次putExtra传递九宫格数据,会增加Intent序列化/反序列化的开销,建议让Puzzle实现Parcelable接口:
@Parcelize class Puzzle(private val grid: Array<IntArray>) : Parcelable { fun get(i: Int, j: Int): Int = grid[i][j] // 其他原有逻辑 }
然后直接传递整个对象:
// 发送方 intent.putExtra("puzzle", puzzle) // 接收方(GameActivity) val puzzle = intent.getParcelableExtra<Puzzle>("puzzle")
3. 排查GameActivity启动延迟的深层原因
如果改造后仍有延迟,需进一步排查:
- 检查
GameActivity的静态代码块、super.onCreate()之前的逻辑是否存在耗时操作 - 查看Application类的
onCreate()方法,是否有第三方SDK初始化、数据库迁移等阻塞操作 - 使用Android Studio的CPU Profiler工具,查看
time2到time3时间段内,主线程的调用栈情况,定位阻塞点
内容的提问来源于stack exchange,提问作者DevNight89
相关产品推荐
相关产品推荐

