如何避免context.getSystemService(Context.CAMERA_SERVICE)中的内存泄漏?

DoD*_*oDo 5 android garbage-collection memory-leaks android-camera

我在Android 5.x Camera2 API中发现了内存泄漏,我也报告过.问题是当您使用在LEGACY模式下实现Camera2 API的Android Lollipop设备时.在这样的设备上,调用context.getSystemService(Context.CAMERA_SERVICE)原因context以便不会被垃圾收集.

如果这context是您多次启动的活动,则最终可能会挂起对活动的数十个实例的挂起引用,这些实例从不被垃圾回收.

问题似乎只发生在LEGACY模式下实现Camera2 API的Lollipop设备上(例如HTC One M8,三星Galaxy S4),而在FULL模式下实现Camera2 API的三星Galaxy S6上则不会发生.

为了演示这个问题,我创建了一个小型演示应用程序.该应用程序包含两个活动:首先包含一个调用第二个活动的按钮.第二个活动获取CameraManager并查询第一个后置摄像头的Camera2 API支持级别,并将结果返回给第一个活动.如果您在LEGACY模式下实现Camera2 API的设备上运行应用程序,在点击按钮98次,导致GC然后转储HPROF后,您将看到98个实时实例Main2Activity,如http://www.pohrani.com/f/ 1H/GS/4EFlHKoj/sgs4.png

如果您在FULL模式下实现Camera2 API的设备上执行相同操作,您将看到0个实时实例Main2Activity,如http://www.pohrani.com/f/2q/bV/4srUZIJL/sgs6.png

有办法解决这个漏洞吗?

有人可能会问为什么我这样做?在我们公司,我们正在开发条形码和OCR扫描解决方案以及着名的PhotoMath应用程序.因此,我们有扫描活动来控制相机和扫描过程.在启动时,活动会检查设备是否支持Camera2 API FULLLIMITED模式,并尝试使用它以获得更好的性能,而如果Camera2 API处于LEGACY模式,那么我们更喜欢使用旧相机API使用相机管理,就像我们在前Lollipop上所做的那样设备.

由于提到的内存泄漏,每当将SDK集成到其应用程序中的客户端启动扫描活动,执行扫描并获得结果时,由于该错误,一个扫描活动实例将被泄露.如果客户端扫描很多,这可能会占用超过20 MB的内存 - 这是一个严重的问题!

因此,如果有人知道如何为此问题制定解决方法,我将永远感激不尽!

Com*_*are 6

有办法解决这个漏洞吗?

你可以打电话getSystemService()Application单身人士.所以,而不是:

getSystemService(CAMERA_SERVICE)
Run Code Online (Sandbox Code Playgroud)

你会用:

getApplicationContext().getSystemService(CAMERA_SERVICE)
Run Code Online (Sandbox Code Playgroud)

如果您的评估是正确的,那么这将导致那些额外的引用到现有的Application单例,这在您的过程中始终存在.它实际上是"预泄漏",你不能通过更多的参考来进一步泄漏它.