当前位置: 首页 > news >正文

RePlugin 坑位使用原理与指南

RePlugin 坑位使用原理与指南

一、坑位机制概述

RePlugin 框架中的"坑位"(Pit)是一种预先注册在宿主 AndroidManifest.xml 中的 Activity/Service/Provider 组件,主要用于承载插件中的组件运行。这种机制使得插件无需修改宿主应用的 manifest 文件,就能动态加载并运行插件组件,有效地解决了 Android 系统对组件注册的严格要求。

坑位机制是 RePlugin 框架最核心的设计之一,它确保了插件框架的稳定性和灵活性,同时使得插件能够像正常安装的应用一样使用四大组件。

二、坑位类型与数量

RePlugin 框架中有以下几种类型的坑位:

1. Activity 坑位

Activity 坑位按照以下维度进行分类:

1.1 透明度分类
  • 透明坑位(Transparent,TS): 用于加载需要透明背景的 Activity
  • 不透明坑位(Non-Transparent,NTS): 用于加载普通 Activity
1.2 启动模式分类

每种透明度类型下,又按照 Android 的四种启动模式细分:

  • standard: 标准模式
  • singleTop: 栈顶复用模式
  • singleTask: 栈内复用模式
  • singleInstance: 单实例模式
1.3 TaskAffinity 分类

为了支持插件中的 TaskAffinity 功能,RePlugin 还提供了专门的 TaskAffinity 坑位组。

2. 进程坑位

RePlugin 支持多进程运行插件,主要有:

  • UI 进程:宿主主进程
  • 常驻进程:插件管理进程,负责插件的加载、通信等
  • 自定义插件进程:可以为插件分配独立进程运行

3. 默认坑位数量

根据 RePluginHostConfig 的默认配置:

// 透明坑位数量
ACTIVITY_PIT_COUNT_TS_STANDARD = 2;
ACTIVITY_PIT_COUNT_TS_SINGLE_TOP = 2;
ACTIVITY_PIT_COUNT_TS_SINGLE_TASK = 2;
ACTIVITY_PIT_COUNT_TS_SINGLE_INSTANCE = 3;// 不透明坑位数量
ACTIVITY_PIT_COUNT_NTS_STANDARD = 6;
ACTIVITY_PIT_COUNT_NTS_SINGLE_TOP = 2;
ACTIVITY_PIT_COUNT_NTS_SINGLE_TASK = 3;
ACTIVITY_PIT_COUNT_NTS_SINGLE_INSTANCE = 2;// TaskAffinity 组数
ACTIVITY_PIT_COUNT_TASK = 2;

三、坑位分配原理

RePlugin 的坑位分配遵循以下原则:

1. Activity 坑位分配流程

  1. 坑位匹配:根据插件 Activity 的启动模式、透明度和 TaskAffinity,找到对应类型的坑位集合
  2. 优先复用:优先查找已分配给相同插件、相同 Activity 的坑位
  3. 空白坑位:如果没有可复用的坑位,则寻找状态为 STATE_NONE 的空白坑位
  4. 回收坑位:如果没有空白坑位,则查找没有引用(没有运行中实例)的最老坑位进行回收
  5. 强制分配:如果所有坑位都在使用中,则选择时间戳最老的坑位,结束其中的 Activity 后重新分配

2. 进程坑位分配流程

StubProcessManager 负责管理进程坑位,主要流程如下:

  1. 进程匹配:根据插件名称找到最合适的进程坑位
  2. 优先级计算:根据以下顺序确定优先级
    • 已分配给相同插件的进程 (优先级最高)
    • 空闲进程
    • 已停止的进程
    • 分配时间超过10秒的进程
    • 没有任何组件的进程
  3. 强制分配:如需要,会终止已有进程并重新分配

3. 坑位分配流程图

singleInstance
非默认TaskAffinity
其他模式
已找到
未找到
找到空白
无空白
找到无引用
无可用
RePlugin.startActivity
Factory.startActivity
PluginCommImpl.startActivity
PluginLibraryInternalProxy.startActivity
loadPluginActivity
获取ActivityInfo
根据进程分配处理
获取或启动插件进程
IPluginClient.allocActivityContainer
client.mContainer.alloc
根据启动模式分类
调用mLaunchModeStates.getStates
调用mTaskAffinityStates.getStates
调用mLaunchModeStates.getStates
allocLocked方法
查找已分配坑位
返回已有坑位
寻找空白坑位
占用空白坑位
查找无引用坑位
占用无引用坑位
强制占用最老坑位
结束已有Activity
重新分配坑位
返回坑位名称
创建Intent并启动Activity

也可以简化为以下基本流程:

┌─────────────────┐     ┌─────────────────┐     ┌─────────────────┐
│                 │     │                 │     │                 │
│  插件 Activity  │────▶│    坑位匹配     │────▶│    坑位分配     │
│                 │     │                 │     │                 │
└─────────────────┘     └─────────────────┘     └────────┬────────┘│▼
┌─────────────────┐     ┌─────────────────┐     ┌─────────────────┐
│                 │     │                 │     │                 │
│   Activity 创建 │◀────│    启动坑位     │◀────│    记录映射     │
│                 │     │                 │     │                 │
└─────────────────┘     └─────────────────┘     └─────────────────┘

四、TaskAffinity 支持机制

TaskAffinity 是 Android 中控制 Activity 分组的机制,RePlugin 通过特殊设计支持插件中的 TaskAffinity:

  1. TaskAffinity 坑位组:提供多组 TaskAffinity 坑位,每组包含不同启动模式的坑位
  2. TaskAffinity 索引计算:通过对插件 Activity 的 taskAffinity 值计算索引,确定使用哪组坑位
  3. 同组复用:相同 TaskAffinity 的 Activity 尽量使用同一组坑位,确保它们在同一个任务栈中

五、坑位状态管理

坑位状态由 ActivityState 类管理,主要有三种状态:

  1. STATE_NONE:未使用状态
  2. STATE_OCCUPIED:已被分配状态
  3. STATE_RESTORED:系统恢复状态(系统恢复 Activity 时使用)

坑位状态变化流程:

  • 分配时:调用 occupy() 方法,状态变为 STATE_OCCUPIED
  • 创建 Activity 时:调用 create() 方法,添加 Activity 引用
  • 销毁 Activity 时:调用 removeRef() 方法,移除 Activity 引用
  • 回收时:调用 recycle() 方法,状态变为 STATE_NONE

六、坑位使用最佳实践

1. 坑位数量配置

在项目中使用 RePlugin 时,可根据实际需求调整坑位数量:

repluginHostConfig {// 常规 Activity 的坑位数countNormalStandard = 8countNormalSingleTop = 4countNormalSingleTask = 6countNormalSingleInstance = 3// 透明 Activity 的坑位数countTranslucentStandard = 3countTranslucentSingleTop = 3countTranslucentSingleTask = 3countTranslucentSingleInstance = 3// TaskAffinity 的坑位组数countTaskAffinity = 4// 是否使用 AppCompat 库useAppCompat = true
}

2. 避免坑位耗尽

合理使用坑位,避免同时打开过多相同类型的 Activity,建议:

  1. 及时关闭不需要的 Activity
  2. 优先使用 standard 启动模式
  3. 使用 Fragment 代替多个功能相似的 Activity

3. TaskAffinity 的合理使用

  1. 避免在插件中定义过多不同的 TaskAffinity
  2. 相似功能的 Activity 尽量使用相同的 TaskAffinity
  3. 注意 TaskAffinity 与启动模式的组合使用

4. 多进程注意事项

  1. 合理规划插件进程分配,避免创建过多进程
  2. 考虑进程间通信成本,非必要时使用同一进程
  3. 注意进程被杀时的状态恢复问题

5. 动态坑位注册

通过使用 registerHookingClass 方法,可以动态注册坑位,使得更灵活地处理插件中的组件:

// 注册 Activity 动态坑位
RePlugin.registerHookingClass("com.example.host.TargetActivity",  // 宿主中定义的目标类名RePlugin.createComponentName("demo1", "com.example.plugin.PluginActivity"),  // 插件中的实际实现类DummyActivity.class  // 默认实现类,通常使用 Dummy 系列类
);

这种方式有以下优势:

  1. 无需预先在宿主 Manifest 中注册大量坑位
  2. 可以按需动态添加插件组件的映射
  3. 适合处理外部调用或 Schema 跳转等场景

6. Schema 支持配置

对于需要支持 Schema 跳转的插件,可通过以下方式配置:

// 1. 在插件初始化时注册 Schema 映射
public static void registerSchemaHandler(Context context) {// 注册外部跳转的入口 ActivityRePlugin.registerHookingClass("com.example.host.SchemaActivity",  // 宿主中的 Schema 处理 ActivityRePlugin.createComponentName("demo1", "com.example.plugin.SchemaActivity"),  // 插件中的接收 ActivityDummyActivity.class);// 注册更多需要支持的 Schema 入口...
}

然后在宿主的 AndroidManifest.xml 中配置 Schema 处理 Activity:

<activity android:name=".SchemaActivity" android:exported="true"><intent-filter><action android:name="android.intent.action.VIEW" /><category android:name="android.intent.category.DEFAULT" /><category android:name="android.intent.category.BROWSABLE" /><data android:scheme="replugin" android:host="demo1" /></intent-filter>
</activity>

这样,外部应用或网页可通过 replugin://demo1/xxxx 的方式直接跳转到插件中的页面。

七、常见问题与解决方案

1. 坑位不足问题

现象:启动插件 Activity 失败,日志提示坑位分配失败。

解决方案

  • 增加对应类型的坑位数量
  • 检查是否有 Activity 没有正确释放
  • 调整 Activity 的启动模式,减少 singleTask/singleInstance 模式的使用
  • 使用 registerHookingClass 方法动态注册坑位

2. TaskAffinity 异常

现象:插件中设置了 TaskAffinity 的 Activity 没有按预期分组。

解决方案

  • 检查 TaskAffinity 坑位组数量是否足够
  • 确保 TaskAffinity 字符串一致
  • 排查启动模式与 TaskAffinity 组合是否正确

3. 进程分配问题

现象:插件运行在非预期的进程中。

解决方案

  • 检查进程指定是否正确
  • 排查是否有其他插件占用了指定进程
  • 增加自定义进程数量

4. Schema 跳转失败

现象:外部通过 Schema URL 无法正确跳转到插件页面。

解决方案

  • 检查宿主 AndroidManifest.xml 中的 Schema 配置是否正确
  • 确认已通过 registerHookingClass 正确注册了 Schema 处理组件
  • 确保插件已正确安装并加载
  • 检查 Schema URL 格式是否符合预期

八、总结

RePlugin 的坑位机制是其核心设计,通过预先注册坑位和动态分配,实现了插件组件的灵活加载和稳定运行。合理配置和使用坑位,对于提高插件框架的稳定性和性能至关重要。

开发者在使用 RePlugin 时,应该根据实际需求合理配置坑位数量,遵循最佳实践,避免坑位资源浪费和耗尽问题,以充分发挥 RePlugin 框架的优势。动态坑位注册和 Schema 支持等高级功能,可以进一步提升插件框架的灵活性和用户体验。

http://www.dtcms.com/a/296974.html

相关文章:

  • 多源信息融合智能投资【“图神经网络+强化学习“的融合架构】【低配显卡正常运行】
  • 模拟退火算法 (Simulated Annealing, SA)简介
  • JavaWeb学习打卡14(JSP内置对象及作用域)
  • ARM汇编常见伪指令及其用法示例
  • IntelliJ IDEA中管理多版本Git子模块的完整指南
  • 智慧工厂网络升级:新型 SD-WAN 技术架构与应用解析
  • 商场导航软件:3D+AI 基于Deepseek 模型的意图识别技术解析
  • BacNet 是什么?跟 LoRaWAN 的关系是什么?
  • 将JS字节流转化为对象
  • 西安交通大学XJTU 通信/信息工程大三和部分大四 实验和课程答案
  • C++哪些运算符不能被重载?
  • kubernetes集群中部署CoreDNS服务
  • day46day47 通道注意力
  • 一种基于单片机控制的太阳能电池板系统设计
  • 集训Demo6
  • 挖掘录屏宝藏:Screenity 深度解析与使用指南
  • 《计算机网络》实验报告八 加密、数字签名与证书
  • pytest测试框架
  • AUTOSAR进阶图解==>AUTOSAR_SWS_BSWGeneral
  • 【Vue学习笔记】状态管理:Pinia 与 Vuex 的使用方法与对比【附有完整案例】
  • 网络安全入门第一课:信息收集实战手册(2)
  • C语言-指针[变量指针与指针变量]
  • Java 集合框架之----ArrayList
  • Effective Modern C++ 条款16:保证const成员函数的线程安全性
  • 网址收集总结
  • 【硬件-笔试面试题】硬件/电子工程师,笔试面试题-17,(知识点:PCB布线,传输线阻抗影响因素)
  • 第一二章笔记
  • [ComfyUI] --ComfyUI 是什么?比 Stable Diffusion WebUI 强在哪?
  • 【STM32项目】智能台灯
  • 无人机保养指南