# UpdateHelper 资源释放机制说明 ## 问题:多次安装会自动释放之前的资源么? **答案:是的,会自动释放。** UpdateHelper 实现了完善的资源释放机制,确保多次安装时不会出现资源泄漏或内存累积问题。 ## 资源释放机制 ### 1. 每次新安装前的资源清理 当通过 `onNewIntent()` 接收到新的安装请求时,会**自动调用 `resetInstallState()`** 清理之前的资源: ```java // onNewIntent() 中的逻辑 if (newApkPath != null && !newApkPath.isEmpty()) { if (isInstalling) { // 如果正在安装中,拒绝新请求 return; } // ✅ 关键:重置状态,清理之前的资源 resetInstallState(); // 然后开始新的安装 startInstall(); } ``` ### 2. resetInstallState() 的清理操作 `resetInstallState()` 方法会执行以下清理操作: ```java private void resetInstallState() { // 1. 取消超时检测 cancelInstallTimeoutCheck(); // 2. 重置安装标志 isInstalling = false; // 3. 清理之前的安装会话 if (currentSession != null) { try { currentSession.abandon(); // 放弃未提交的会话 currentSession.close(); // 关闭会话 } catch (Exception e) { // 处理异常 } currentSession = null; } currentSessionId = -1; // 4. 建议系统进行垃圾回收 System.gc(); // 5. 重置界面状态 // ... } ``` ### 3. 安装过程中的资源管理 #### a) 文件流的自动关闭 使用 try-with-resources 或显式关闭确保文件流被释放: ```java InputStream in = null; OutputStream out = null; try { in = new FileInputStream(apkFile); out = currentSession.openWrite("package", 0, apkSize); // ... 读取和写入操作 ... // 显式关闭流 if (out != null) { out.close(); out = null; } if (in != null) { in.close(); in = null; } // 建议 GC 释放内存 System.gc(); } catch (Exception e) { // 异常时也确保关闭流 cleanupResources(in, out); throw e; } ``` #### b) 会话的正确关闭 - **成功时**:`commit()` 后立即 `close()`,会话被系统接管 - **失败时**:调用 `abandon()` 放弃会话,然后 `close()` ```java // 成功提交 currentSession.commit(pendingIntent.getIntentSender()); currentSession.close(); currentSession = null; // 失败时 if (currentSession != null) { currentSession.abandon(); // 放弃会话 currentSession.close(); // 关闭会话 currentSession = null; } ``` ### 4. Activity 销毁时的清理 在 `onDestroy()` 中也会清理资源: ```java @Override protected void onDestroy() { super.onDestroy(); // 取消超时检测 cancelInstallTimeoutCheck(); // 清理安装会话 if (currentSession != null) { try { currentSession.close(); } catch (Exception e) { // 处理异常 } } } ``` ## 资源释放的时机 | 时机 | 释放的资源 | 方法 | |------|-----------|------| | **新安装请求时** | 之前的会话、超时检测、内存 | `resetInstallState()` | | **安装成功时** | 文件流、会话(提交后关闭) | `performInstall()` 正常流程 | | **安装失败时** | 文件流、会话(放弃后关闭) | `performInstall()` 异常处理 | | **Activity 销毁时** | 会话、超时检测 | `onDestroy()` | ## 内存管理优化 ### 1. 垃圾回收建议 在关键时机建议系统进行垃圾回收: - **处理大文件前**(>100MB):`System.gc()` - **文件流关闭后**:`System.gc()` - **重置安装状态时**:`System.gc()` ### 2. 缓冲区大小优化 使用较小的缓冲区(32KB)减少峰值内存使用: ```java byte[] buffer = new byte[32768]; // 32KB 缓冲区 ``` ### 3. 大堆内存支持 在 `AndroidManifest.xml` 中启用 `largeHeap="true"`,提供更大的堆内存空间。 ## 验证资源释放 ### 测试场景 1. **连续多次安装** - 第一次安装完成后,立即开始第二次安装 - 验证不会出现内存不足错误 2. **安装失败后重试** - 第一次安装失败后,立即重试 - 验证资源被正确清理 3. **快速切换安装任务** - 在安装过程中(如果允许)或安装完成后快速启动新安装 - 验证之前的会话被正确清理 ### 监控指标 可以通过以下方式监控资源释放: ```java // 获取运行时内存信息 Runtime runtime = Runtime.getRuntime(); long totalMemory = runtime.totalMemory(); long freeMemory = runtime.freeMemory(); long usedMemory = totalMemory - freeMemory; Log.d(TAG, "内存使用: " + (usedMemory / 1024 / 1024) + " MB"); ``` ## 注意事项 1. **System.gc() 不保证立即执行** - `System.gc()` 只是建议,不保证立即执行 - 系统会在合适的时机进行垃圾回收 2. **会话状态检查** - 如果会话已提交,`abandon()` 会抛出 `IllegalStateException` - 代码中已处理此异常,这是正常情况 3. **并发控制** - `isInstalling` 标志防止并发安装 - 如果正在安装中,新的安装请求会被拒绝 ## 总结 UpdateHelper 实现了完善的资源释放机制: ✅ **自动释放**:每次新安装前自动清理之前的资源 ✅ **异常安全**:即使出现异常,也会确保资源被释放 ✅ **内存优化**:通过 GC 建议和缓冲区优化减少内存占用 ✅ **生命周期管理**:在 Activity 销毁时也会清理资源 因此,**多次安装会自动释放之前的资源**,不会出现资源泄漏或内存累积问题。