# 分享模块重构方案 - 移除 ShareProxyActivity ## 一、现状分析 ### 1.1 当前架构 当前分享模块使用 **ShareProxyActivity** 作为透明代理 Activity 来统一处理所有平台的分享回调: ``` 业务层调用 shareService.share(activity, content, callback) ↓ 自动启动 ShareProxyActivity(透明) ↓ ShareProxyActivity.onCreate() 调用 shareService.shareManual() ↓ 执行实际分享(友盟SDK) ↓ 用户在第三方应用完成分享 ↓ 第三方应用回调 → ShareProxyActivity.onActivityResult() ↓ ShareProxyActivity 调用 shareService.onActivityResult() ↓ 处理回调并传递给业务层 ↓ ShareProxyActivity 自动关闭 ``` ### 1.2 当前实现的关键点 1. **ShareProxyActivity**: - 透明的代理 Activity,用户看不到 - 统一处理所有平台的 `onActivityResult` 回调 - 业务层无需在 Activity 中处理回调 2. **share() 方法**: - 自动启动 `ShareProxyActivity` - 内部使用 `shareManual()` 避免递归调用 3. **shareManual() 方法**: - 供 `ShareProxyActivity` 内部调用 - 直接执行分享逻辑,不启动代理 Activity 4. **onActivityResult() 方法**: - 由 `ShareProxyActivity` 调用 - 转发给友盟 SDK 处理 ### 1.3 当前架构的优势 ✅ **业务层透明**:业务层不需要处理 `onActivityResult` ✅ **统一处理**:所有平台的回调都统一在 `ShareProxyActivity` 中处理 ✅ **完全封装**:实现细节完全封装在模块内部 ### 1.4 当前架构的问题 ❌ **依赖 Activity**:必须启动一个透明的 Activity ❌ **生命周期复杂**:需要管理 Activity 的生命周期和超时 ❌ **增加 Activity 栈**:每次分享都会启动新的 Activity ❌ **灵活性不足**:无法让业务层自行处理回调 --- ## 二、重构目标 ### 2.1 需求 1. **移除 ShareProxyActivity**:不通过代理 Activity 统一处理 2. **只暴露方法**:所有功能都通过方法暴露 3. **统一入口**:提供一个统一的分享方法给外部调用 4. **业务层自行处理回调**:业务层需要在 Activity 中处理 `onActivityResult` ### 2.2 重构后的架构 ``` 业务层调用 shareService.share(activity, content, callback) ↓ 直接执行分享(友盟SDK) ↓ 用户在第三方应用完成分享 ↓ 第三方应用回调 → 业务层 Activity.onActivityResult() ↓ 业务层调用 shareService.onActivityResult() ↓ 处理回调并传递给业务层 ``` --- ## 三、重构方案 ### 3.1 API 设计 #### 3.1.1 统一分享方法 所有分享都通过一个统一的 `share()` 方法: ```kotlin interface ShareService { /** * 统一分享方法(推荐使用) * * 如果 ShareContent.platform 已指定,则直接分享到该平台 * 如果 ShareContent.platform 为 null,则显示分享弹窗让用户选择平台 * * 注意:业务层需要在 Activity.onActivityResult() 中调用 shareService.onActivityResult() * * @param activity Activity上下文 * @param content 分享内容 * @param callback 分享结果回调 */ fun share(activity: Activity, content: ShareContent, callback: (ShareResponse) -> Unit) /** * 处理分享回调(必须在 Activity.onActivityResult() 中调用) * * 业务层必须在 Activity.onActivityResult() 中调用此方法,以接收分享结果 * * @param activity Activity上下文 * @param requestCode 请求码 * @param resultCode 结果码 * @param data Intent数据 */ fun onActivityResult(activity: Activity, requestCode: Int, resultCode: Int, data: Intent?) } ``` #### 3.1.2 各平台分享方法(可选,向后兼容) 保留各平台的具体分享方法,但都改为直接调用,不通过代理 Activity: ```kotlin interface ShareService { // 统一分享方法(推荐) fun share(activity: Activity, content: ShareContent, callback: (ShareResponse) -> Unit) // 各平台分享方法(可选,向后兼容) fun shareToWeChat(activity: Activity, content: ShareContent, callback: (ShareResponse) -> Unit) fun shareToWeChatMoments(activity: Activity, content: ShareContent, callback: (ShareResponse) -> Unit) fun shareToQQ(activity: Activity, content: ShareContent, callback: (ShareResponse) -> Unit) fun shareToQZone(activity: Activity, content: ShareContent, callback: (ShareResponse) -> Unit) fun shareToWeibo(activity: Activity, content: ShareContent, callback: (ShareResponse) -> Unit) fun shareToDouyin(activity: Activity, content: ShareContent, callback: (ShareResponse) -> Unit) fun shareToXiaohongshu(activity: Activity, content: ShareContent, callback: (ShareResponse) -> Unit) fun shareToKuaishou(activity: Activity, content: ShareContent, callback: (ShareResponse) -> Unit) fun shareToSystem(activity: Activity, content: ShareContent, callback: (ShareResponse) -> Unit) // 显示分享弹窗 fun showShareDialog(activity: Activity, content: ShareContent, callback: (ShareResponse) -> Unit) // 必须调用:处理分享回调 fun onActivityResult(activity: Activity, requestCode: Int, resultCode: Int, data: Intent?) } ``` ### 3.2 实现改动 #### 3.2.1 ShareService 接口改动 ```kotlin interface ShareService { // 移除 shareManual() 方法(不再需要) // 移除:fun shareManual(activity: Activity, content: ShareContent, callback: (ShareResponse) -> Unit) // share() 方法改为直接执行,不启动 ShareProxyActivity fun share(activity: Activity, content: ShareContent, callback: (ShareResponse) -> Unit) { // 如果指定了平台,直接分享到该平台 if (content.platform != null) { shareToPlatform(activity, content, content.platform, callback) } else { // 否则显示分享弹窗 showShareDialog(activity, content, callback) } } } ``` #### 3.2.2 ShareServiceImpl 实现改动 ```kotlin class ShareServiceImpl : ShareService { // 存储回调(用于 onActivityResult 时查找) private val callbacks = mutableMapOf Unit>() private var requestCodeCounter = 1000 override fun share(activity: Activity, content: ShareContent, callback: (ShareResponse) -> Unit) { // 不再启动 ShareProxyActivity,直接执行分享 if (content.platform != null) { shareToPlatform(activity, content, content.platform, callback) } else { showShareDialog(activity, content, callback) } } private fun shareToPlatform( activity: Activity, content: ShareContent, platform: SharePlatform, callback: (ShareResponse) -> Unit ) { // 生成唯一的 requestCode val requestCode = requestCodeCounter++ callbacks[requestCode] = callback // 调用友盟 SDK 进行分享 val shareMedia = createShareMedia(activity, content) val shareAction = ShareAction(activity) shareAction.withMedia(shareMedia) shareAction.setPlatform(toShareMedia(platform)) shareAction.setCallback(createShareListener(platform, requestCode, callback)) shareAction.share() } override fun onActivityResult(activity: Activity, requestCode: Int, resultCode: Int, data: Intent?) { // 转发给友盟 SDK 处理 UMShareAPI.get(activity).onActivityResult(requestCode, resultCode, data) } private fun createShareListener( platform: SharePlatform, requestCode: Int, callback: (ShareResponse) -> Unit ): UMShareListener { return object : UMShareListener { override fun onResult(shareMedia: SHARE_MEDIA?) { // 找到对应的回调并调用 callbacks[requestCode]?.invoke( ShareResponse(success = true, data = platform) ) callbacks.remove(requestCode) } override fun onError(shareMedia: SHARE_MEDIA?, throwable: Throwable?) { callbacks[requestCode]?.invoke( ShareResponse( success = false, data = platform, errorMessage = throwable?.message ) ) callbacks.remove(requestCode) } override fun onCancel(shareMedia: SHARE_MEDIA?) { callbacks[requestCode]?.invoke( ShareResponse( success = false, data = platform, errorMessage = "用户取消分享" ) ) callbacks.remove(requestCode) } } } } ``` #### 3.2.3 移除 ShareProxyActivity - 删除 `ShareProxyActivity.kt` 文件 - 从 `AndroidManifest.xml` 中移除 `ShareProxyActivity` 的声明 - 移除 `shareManual()` 方法(不再需要) ### 3.3 业务层改动 #### 3.3.1 使用示例(Fragment) ```kotlin class UserFragment : Fragment() { private val shareService = ShareServiceFactory.getInstance() private fun shareContent() { val content = ShareContent.builder() .setTitle("分享标题") .setDescription("分享描述") .setUrl("https://example.com") .build() // 调用统一分享方法 shareService.share(requireActivity(), content) { response -> if (response.success) { Toast.makeText(requireContext(), "分享成功", Toast.LENGTH_SHORT).show() } else { Toast.makeText(requireContext(), "分享失败: ${response.errorMessage}", Toast.LENGTH_SHORT).show() } } } } ``` #### 3.3.2 必须处理 onActivityResult **重要**:业务层必须在 Activity 中处理 `onActivityResult`: ```kotlin class MainActivity : AppCompatActivity() { private val shareService = ShareServiceFactory.getInstance() override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { super.onActivityResult(requestCode, resultCode, data) // 必须调用:处理分享回调 shareService.onActivityResult(this, requestCode, resultCode, data) } } ``` ### 3.4 兼容性考虑 #### 3.4.1 向后兼容 - 保留所有现有的 API 方法(`shareToWeChat()`, `shareToQQ()` 等) - 只是改变实现方式(不再通过 ShareProxyActivity) - 业务层代码改动最小化 #### 3.4.2 迁移指南 1. **必须添加**:在 Activity 中添加 `onActivityResult()` 处理 2. **无需改动**:调用 `share()` 方法的代码无需改动 3. **可选**:可以继续使用各平台的具体方法(`shareToWeChat()` 等) --- ## 四、重构步骤 ### 步骤 1:修改 ShareService 接口 - [ ] 移除 `shareManual()` 方法 - [ ] 更新 `share()` 方法的文档说明 ### 步骤 2:修改 ShareServiceImpl 实现 - [ ] 修改 `share()` 方法,不再启动 `ShareProxyActivity` - [ ] 实现回调管理(使用 Map 存储回调) - [ ] 修改各平台分享方法,使用回调管理 - [ ] 更新 `onActivityResult()` 方法,从回调 Map 中查找并调用回调 ### 步骤 3:移除 ShareProxyActivity - [ ] 删除 `ShareProxyActivity.kt` 文件 - [ ] 从 `AndroidManifest.xml` 中移除相关声明 - [ ] 清理相关引用 ### 步骤 4:更新文档 - [ ] 更新 `集成说明.md` - [ ] 添加 `onActivityResult()` 处理说明 - [ ] 更新使用示例 ### 步骤 5:测试 - [ ] 测试各平台分享功能 - [ ] 测试分享回调处理 - [ ] 测试分享弹窗功能 --- ## 五、优缺点分析 ### 5.1 优点 ✅ **灵活性更高**:业务层可以自行处理回调 ✅ **减少 Activity 栈**:不再启动代理 Activity ✅ **代码更简洁**:移除复杂的 Activity 生命周期管理 ✅ **更符合 Android 规范**:业务层直接处理回调 ### 5.2 缺点 ❌ **增加业务层负担**:业务层必须在 Activity 中处理 `onActivityResult` ❌ **可能遗漏回调**:如果业务层忘记处理 `onActivityResult`,分享回调将丢失 ❌ **Fragment 使用不便**:Fragment 需要依赖 Activity 的 `onActivityResult` --- ## 六、注意事项 1. **必须处理 onActivityResult**:业务层必须在 Activity 中调用 `shareService.onActivityResult()` 2. **Fragment 使用**:Fragment 需要确保 Activity 正确处理 `onActivityResult` 3. **回调管理**:需要实现回调的存储和查找机制(使用 requestCode 作为 key) 4. **内存泄漏**:需要确保回调能够及时清理,避免内存泄漏 --- ## 七、总结 重构后的分享模块: - ✅ 移除了 `ShareProxyActivity`,不再通过代理 Activity 处理回调 - ✅ 所有功能都通过方法暴露,提供统一的 `share()` 方法 - ✅ 业务层需要自行处理 `onActivityResult` - ✅ 保持向后兼容,现有 API 仍然可用 这个方案更符合 Android 的开发规范,也给了业务层更多的控制权。