MLKit姿态检测APP内存溢出崩溃问题求助(Kotlin)
Kotlin下MLKit姿态估计APP内存崩溃解决方案
核心问题分析
原代码存在多处内存浪费与资源未合理释放的问题:
- 重复创建Bitmap:从TextureView获取
bm后,额外通过压缩再解码生成新Bitmap,无端占用内存 - 字符串拼接低效:循环中用
+=拼接字符串,会生成大量临时String对象 - 未及时回收Bitmap资源:使用后的Bitmap未主动释放,导致内存堆积
- 帧处理无节流:短时间内处理过多帧,引发内存缓冲区耗尽
具体修复方案
- 避免重复创建Bitmap:直接用TextureView获取的Bitmap创建InputImage,跳过冗余的压缩解码流程
- 优化字符串拼接:改用
StringBuilder减少临时对象生成 - 主动回收Bitmap:在确认不再使用Bitmap时调用
recycle()释放内存 - 添加帧节流:控制处理帧率,避免短时间内任务堆积
- 优化视图资源:移除视图时确保相关资源被释放,避免内存泄漏
修改后的代码
// 新增帧节流控制,限制每秒处理5帧 private var lastProcessTime = 0L private val processInterval = 200L // 200ms间隔 Log.d("LOG:", "Here") val bm = mTextureView.bitmap val currentTime = System.currentTimeMillis() if (bm != null && currentTime - lastProcessTime > processInterval) { lastProcessTime = currentTime Log.d("LOG:", "not null") // 直接用原Bitmap创建InputImage,省去重复解码步骤 val inputImage = InputImage.fromBitmap(bm, 0) poseDetector.process(inputImage) .addOnSuccessListener { pose -> if (parentLayout.childCount > 4) { val removedView = parentLayout.getChildAt(4) parentLayout.removeView(removedView) // 如果Draw类持有自定义资源,可在此调用回收方法,比如removedView.release() } imgView.setImageBitmap(bm) if (pose.allPoseLandmarks.isNotEmpty()) { val draw = Draw(applicationContext, pose) parentLayout.addView(draw) // 用StringBuilder优化字符串拼接,减少内存开销 val contentBuilder = StringBuilder() pose.allPoseLandmarks.forEach { contentBuilder.append(it.position3D.x) .append(",") .append(it.position3D.y) .append(",") .append(it.position3D.z) .append(",") .append(it.inFrameLikelihood) .append(",") } contentBuilder.append("\n") val content = contentBuilder.toString() println(content) fileOut.appendText(content) Log.d("LOG:", "Success") } // 处理完成后回收Bitmap(确认后续不再使用时调用) if (!bm.isRecycled) { bm.recycle() } } .addOnFailureListener { Log.d("LOG:", "Failure: ${it.message}") // 失败场景下也回收Bitmap if (!bm.isRecycled) { bm.recycle() } } } else { Log.d("LOG:", if (bm == null) "null" else "skip frame for throttle") }
额外优化建议
- 使用
LruCache缓存Bitmap,减少频繁创建与销毁的开销 - 确保
fileOut在使用完毕后正确关闭,避免IO资源泄漏 - 在Activity/Fragment销毁时调用
poseDetector.close(),释放MLKit相关资源 - 借助Android Studio Profiler工具,定位具体内存泄漏点
内容的提问来源于stack exchange,提问作者Firas SOLTANI
相关产品推荐
相关产品推荐

