资源释放机制说明.md 5.6 KB

UpdateHelper 资源释放机制说明

问题:多次安装会自动释放之前的资源么?

答案:是的,会自动释放。 UpdateHelper 实现了完善的资源释放机制,确保多次安装时不会出现资源泄漏或内存累积问题。

资源释放机制

1. 每次新安装前的资源清理

当通过 onNewIntent() 接收到新的安装请求时,会自动调用 resetInstallState() 清理之前的资源:

// onNewIntent() 中的逻辑
if (newApkPath != null && !newApkPath.isEmpty()) {
    if (isInstalling) {
        // 如果正在安装中,拒绝新请求
        return;
    }
    
    // ✅ 关键:重置状态,清理之前的资源
    resetInstallState();
    
    // 然后开始新的安装
    startInstall();
}

2. resetInstallState() 的清理操作

resetInstallState() 方法会执行以下清理操作:

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 或显式关闭确保文件流被释放:

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()

    // 成功提交
    currentSession.commit(pendingIntent.getIntentSender());
    currentSession.close();
    currentSession = null;
    
    // 失败时
    if (currentSession != null) {
    currentSession.abandon();  // 放弃会话
    currentSession.close();     // 关闭会话
    currentSession = null;
    }
    

4. Activity 销毁时的清理

onDestroy() 中也会清理资源:

@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)减少峰值内存使用:

byte[] buffer = new byte[32768]; // 32KB 缓冲区

3. 大堆内存支持

AndroidManifest.xml 中启用 largeHeap="true",提供更大的堆内存空间。

验证资源释放

测试场景

  1. 连续多次安装

    • 第一次安装完成后,立即开始第二次安装
    • 验证不会出现内存不足错误
  2. 安装失败后重试

    • 第一次安装失败后,立即重试
    • 验证资源被正确清理
  3. 快速切换安装任务

    • 在安装过程中(如果允许)或安装完成后快速启动新安装
    • 验证之前的会话被正确清理

监控指标

可以通过以下方式监控资源释放:

// 获取运行时内存信息
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 销毁时也会清理资源

因此,多次安装会自动释放之前的资源,不会出现资源泄漏或内存累积问题。