Android面试题——掘金-三方框架之Shadow(5.3)

一 概述

1
Android 三方框架相关面试题:Shadow 插件化框架

二 面试题解答(仅供参考)

2.1 什么是 Shadow?它的作用是什么?

1
2
3
4
5
1.概念
Shadow 是腾讯开源的 Android 插件化框架,
用于解决传统插件化中需对宿主进行侵入式改造的问题,目的是 实现真正的“宿主无感知”插件化。

2.核心作用:让插件像普通 App 一样运行,而宿主无须改变任何代码逻辑或资源配置。

2.2 Shadow 与传统插件化框架(如 RePlugin、Small、DroidPlugin)有什么不同?

特性 Shadow RePlugin / DroidPlugin 等
插件资源访问 支持原生资源访问 需特殊资源 ID 适配处理
插件 Activity 启动 完整支持 startActivity 需要通过代理或桥接
宿主无侵入 ✅ 是 ❌ 需要改造宿主 Manifest/源码
插件进程/生命周期 完整隔离,真实 Activity 生命周期 有些通过代理 Activity 实现
插件打包 通过 Gradle 插件统一化 大多数需手动配置

2.3 Shadow 的整体架构是什么?

1
2
3
4
5
6
7
8
Shadow 的架构主要包括:
-宿主 Host(Manager):真正安装在手机的 APK,作用是负责插件加载;
-插件 Plugin:独立的 APK,包含自身的资源与组件;
-Loader:加载插件 dex 的 ClassLoader;
-PluginManager:插件生命周期控制器;
-PluginContainer(壳 Activity):容器,用于承载插件 Activity。

宿主并不直接引用插件代码,运行时动态加载 + ClassLoader 隔离。

2.4 Shadow 的 Activity 是如何启动的?

1
2
3
4
5
6
7
8
9
Shadow 使用 “壳 Activity + 插件 Activity 替换” 的机制。

流程如下:
-插件调用 startActivity(Intent);
-替换 Intent 为壳 Activity;
-加载插件 APK 的 ClassLoader;
-创建插件 Activity 实例;
-将生命周期方法 onCreate 等通过委托或代理调用插件;
-插件像普通 Activity 一样运行,用户无感知。

2.5 Shadow 的 ClassLoader 是怎么处理插件隔离的?

1
2
3
4
5
6
Shadow 使用自定义的 PluginClassLoader:

-宿主与插件拥有各自的 ClassLoader;
-插件加载自身类时优先使用插件 ClassLoader;
-插件无法访问宿主代码,宿主也无法直接访问插件类;
-保证安全性、隔离性、热更新能力。

2.6 Shadow 如何加载插件资源?如何解决 Resource ID 冲突?

1
2
3
4
5
-插件 APK 是 独立构建 的,资源不依赖宿主;
-使用 Shadow 提供的 PluginResourceLoader 注入插件资源路径;
-插件运行时构建一个新的 Resources 对象(通过 AssetManager 添加插件资源路径);
-通过 hook 替换插件 Context 的 getResources() 实现插件资源访问;
-插件的资源 ID 与宿主完全隔离,避免冲突。

2.7 Shadow 如何支持插件的 Service / BroadcastReceiver / ContentProvider?

1
2
3
4
5
-Service:通过 hook AMS,拦截 startService,映射到插件;
-BroadcastReceiver:Shadow 支持插件中注册 Receiver,并通过代理处理;
-ContentProvider:目前一般通过宿主转发方式实现或使用 ContentProvider Bridge;

⚠️ Provider 由于系统自动初始化,插件需延迟初始化或使用虚拟层代理。

2.8 Shadow 的插件如何打包与构建?

1
2
3
4
5
6
使用官方提供的 Gradle 插件 shadow-plugin,步骤如下:

1.在插件模块中引入 com.tencent.shadow.plugin
2.插件需构建为 .apk,不参与宿主编译;
3.插件代码、资源完全隔离,独立配置包名、权限等;
4.构建产物会生成 plugin-debug.apk、manager-debug.apk 等模块。

2.9 Shadow 是否支持插件热更新?如何实现?

1
2
3
4
5
6
Shadow 插件在运行时由宿主动态加载,因此:

-插件 APK 可下载后替换;
-使用 PluginManager.loadPlugin(path) 实现重新加载;
-可与差量更新方案(如 Tinker、bspatch)结合实现热修复;
-因为插件无宿主耦合,也不影响主包安全性。

2.10 使用 Shadow 插件化有哪些限制或注意点?

1
2
3
4
5
-插件中不可直接引用宿主类或资源;
-插件必须使用 Shadow 的 Gradle 插件打包;
-插件之间通信需要通过桥接(如接口 + JSON + Binder);
-插件初始化逻辑需在插件 Application 或 Service 手动完成;
-插件权限声明需在插件 APK 中独立定义;

2.11 Shadow 的 Activity 是如何管理生命周期的?

1
2
3
4
5
通过宿主壳 Activity 转发生命周期事件:

-PluginActivity 接收 onCreate/onStart/... 的代理调用;
-PluginContainerActivity 调用插件类的生命周期函数;
-插件生命周期与宿主生命周期完全同步,符合系统行为。

2.12 Shadow 和模块化(Module)、组件化(ARouter)有什么区别?

特性 模块化 / ARouter Shadow 插件化
编译时依赖
是否独立 否(最终打成主包) 是(单独 APK)
是否可更新 ✅ 可热更新
生命周期隔离 ✅ 是
使用场景 大型工程分模块管理 插件市场、业务解耦、热更新等

2.13 总结

维度 说明
插件隔离 类、资源完全隔离
插件加载 动态加载 dex 和资源
生命周期 插件与宿主同步管理
插件通信 通过桥接或远程接口
热更新支持 ✅ 支持
构建方式 独立 APK + Gradle 插件

三 参考

  • 掘金—知识库的大纲