Android多Activity间onData方法复用异常及ServiceConnection泄漏问题
看起来你遇到的两个问题本质上是同一个原因:旧Activity的EMDK资源没有彻底释放,导致服务连接和回调监听器仍然绑定在已销毁的Activity实例上。我来帮你拆解问题并给出具体的修复方案:
问题根源分析
新Activity调用旧Activity的
onData:
旧Activity虽然通过finish()销毁了,但你在onPause里的资源释放不彻底——BarcodeManager可能还持有旧Activity的ConnectionListener引用,当扫描触发时,EMDK服务仍然会把回调发送给这个已失效的实例。ServiceConnection泄漏错误:
EMDK的服务连接(EMDKServiceConnection)是绑定在旧Activity上的,如果Activity销毁时没有正确解绑并释放EMDKManager,系统会检测到这个连接被已销毁的Activity持有,从而抛出泄漏警告。
修复方案:完善资源释放逻辑
你需要在Activity的**onDestroy方法**中做彻底的资源清理(而不是只在onPause里处理),因为onPause只是Activity失去焦点时的回调,不一定会触发销毁;而onDestroy是Activity生命周期的最后一步,在这里释放资源能确保所有绑定都被清理。
修改后的代码示例
首先补充onDestroy方法,同时调整onPause里的逻辑(避免重复释放或释放不彻底):
// 先完善onDestroy方法,做彻底的资源清理 @Override protected void onDestroy() { super.onDestroy(); // 1. 停止并销毁扫描器 if (scanner != null) { try { // 先取消当前的扫描读取 scanner.cancelRead(); // 销毁扫描器实例 scanner.destroy(); } catch (ScannerException e) { e.printStackTrace(); } scanner = null; } // 2. 移除BarcodeManager的监听器并置空 if (barcodeManager != null) { barcodeManager.removeConnectionListener(this); barcodeManager = null; } // 3. 释放EMDKManager的BARCODE特性并置空 if (emdkManager != null) { emdkManager.release(EMDKManager.FEATURE_TYPE.BARCODE); emdkManager = null; } } // 调整onPause方法,只处理暂停时的必要操作(比如停止扫描) @Override protected void onPause() { super.onPause(); // 暂停时停止扫描即可,不要在这里释放EMDKManager if (scanner != null) { try { scanner.cancelRead(); } catch (ScannerException e) { e.printStackTrace(); } } deInitScanner(); } // 保留原有的onResume逻辑,确保新Activity初始化时独立绑定EMDK @Override protected void onResume() { super.onResume(); if (emdkManager != null) { barcodeManager = (BarcodeManager) emdkManager.getInstance(EMDKManager.FEATURE_TYPE.BARCODE); if (barcodeManager != null) { barcodeManager.addConnectionListener(this); } enumerateScannerDevices(); spinnerScannerDevices.setSelection(scannerIndex); try { initScanner(); } catch (ScannerException e) { e.printStackTrace(); } scanner.triggerType = Scanner.TriggerType.HARD; } }
关键注意事项
- 释放顺序不能乱:必须先处理扫描器(停止→销毁),再移除BarcodeManager监听器,最后释放EMDKManager,这样能确保所有引用链被彻底切断。
- 每个Activity独立管理EMDK资源:两个Activity的EMDK实例不要共享,各自在
onResume初始化,onDestroy释放,保证生命周期完全独立。 - 避免在onPause中释放核心资源:如果只是切换到后台(比如按Home键),
onPause后Activity还会存在,此时释放EMDKManager会导致再次进入时需要重新绑定,反而容易出问题。
这样修改后,旧Activity销毁时会彻底清理所有EMDK相关的绑定和资源,新Activity的onData回调就不会再触发旧实例的方法,ServiceConnection泄漏的问题也会解决。
内容的提问来源于stack exchange,提问作者Zak

