【Android 组件化】路由组件 ( 运行时获取 注解处理器 生成的路由表 )
组件化系列博客 :
- 【Android 组件化】从模块化到组件化
- 【Android 组件化】使用 Gradle 实现组件化 ( Gradle 变量定义与使用 )
- 【Android 组件化】使用 Gradle 实现组件化 ( 组件模式与集成模式切换 )
- 【Android 组件化】使用 Gradle 实现组件化 ( 组件 / 集成模式下的 Library Module 开发 )
- 【Android 组件化】路由组件 ( 路由组件结构 )
- 【Android 组件化】路由组件 ( 注解处理器获取被注解的节点 )
- 【Android 组件化】路由组件 ( 注解处理器中使用 JavaPoet 生成代码 )
- 【Android 组件化】路由组件 ( 注解处理器参数选项设置 )
- 【Android 组件化】路由组件 ( 构造路由表中的路由信息 )
- 【Android 组件化】路由组件 ( 使用 JavaPoet 生成路由表类 )
- 【Android 组件化】路由组件 ( 组件间共享的服务 )
- 【Android 组件化】路由组件 ( 生成 Root 类记录模块中的路由表 )
一、获取应用的 APK
获取应用的 APK 文件 :
首先 , 获取 ApplicationInfo 应用信息 ;
ApplicationInfo applicationInfo = null;
try {
applicationInfo = mContext.getPackageManager().getApplicationInfo(mContext
.getPackageName(), 0);
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
然后 , 从应用中获取 APK 的安装路径 ;
// 使用集合存放应用安装的 APK 文件
List<String> sourcePaths = new ArrayList<>();
// 一般情况下 , 一个应用只有一个安装 APK
sourcePaths.add(applicationInfo.sourceDir);
- 1
- 2
- 3
- 4
- 5
最后 , 考虑 instant run 的情况 , 可能存在多个 APK 文件 , 如果有多个 , 也一并放入路径字符串集合中 ;
// 如果是 instant run 形式安装的 , 则有多个 APK 文件
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
if (null != applicationInfo.splitSourceDirs) {
sourcePaths.addAll(Arrays.asList(applicationInfo.splitSourceDirs));
}
}
- 1
- 2
- 3
- 4
- 5
- 6
代码示例 :
ApplicationInfo applicationInfo = null;
try {
applicationInfo = mContext.getPackageManager().getApplicationInfo(mContext
.getPackageName(), 0);
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
}
// 使用集合存放应用安装的 APK 文件
List<String> sourcePaths = new ArrayList<>();
// 一般情况下 , 一个应用只有一个安装 APK
sourcePaths.add(applicationInfo.sourceDir);
// 如果是 instant run 形式安装的 , 则有多个 APK 文件
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
if (null != applicationInfo.splitSourceDirs) {
sourcePaths.addAll(Arrays.asList(applicationInfo.splitSourceDirs));
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
二、获取所有 APK 中 kim.hsl.router 包的类
获取所有 APK 中 kim.hsl.router 包的类 :
首先 , 根据 APK 的地址 , 创建 DexFile 对象 ;
// 获取 APK 下的 dex 文件
DexFile dexfile = null;
try {
dexfile = new DexFile(path);
} catch (IOException e) {
e.printStackTrace();
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
然后 , 遍历 DexFile 对象中的所有的类 , 调用 dexfile.entries() 获取 Enumeration<String> 对象进行遍历 , 将 “kim.hsl.router” 包名下的类记录下来 ;
Enumeration<String> dexEntries = dexfile.entries();
// 遍历 DEX 文件中的所有的类
while (dexEntries.hasMoreElements()) {
String className = dexEntries.nextElement();
if (className.startsWith("kim.hsl.router")) {
classNames.add(className);
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
代码示例 :
/*
根据获取所有 APK 下的类
根据 kim.hsl.router 包名, 获取该包名下的所有路由类
*/
// 获取查找的 kim.hsl.router 包下的类 的 类名
Set<String> classNames = new HashSet<>();
// 遍历所有的 APK 路径 , 查找其中的 DEX 中的类
for (final String path : sourcePaths) {
// 获取 APK 下的 dex 文件
DexFile dexfile = null;
try {
dexfile = new DexFile(path);
} catch (IOException e) {
e.printStackTrace();
}
Enumeration<String> dexEntries = dexfile.entries();
// 遍历 DEX 文件中的所有的类
while (dexEntries.hasMoreElements()) {
String className = dexEntries.nextElement();
if (className.startsWith("kim.hsl.router")) {
classNames.add(className);
}
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
三、获取其它 Module 中的路由表
之前已经获取了 “kim.hsl.router” 包中的所有类 , 将 " kim.hsl.router.Router_Root_ " 开头的类记录下来 , 使用反射获取相关类 , 可以直接创建 Root 表对应的对象 ;
代码示例 :
// 最终所有的 kim.hsl.router 包下的类都存放到了 Set<String> classNames 变量中
for (String className : classNames){
/*
这是打印出来的类
kim.hsl.router_annotation.model.RouteBean$Type
kim.hsl.router.Router_Group_app
kim.hsl.router_annotation.Route
kim.hsl.router.Router_Root_library2
kim.hsl.router.Router_Root_app
kim.hsl.router.Router_Group_library2
kim.hsl.router_annotation.model.RouteBean
*/
Log.i(TAG, "loadInfo : " + className);
// 如果该类以 " Router_Root_ " 开头 , 说明这是 Root 表类
if (className.startsWith("kim.hsl.router.Router_Root_")) {
// root中注册的是分组信息 将分组信息加入仓库中
try {
// 获取 IRouteRoot 类
Class<IRouteRoot> clazz = (Class<IRouteRoot>) Class.forName(className);
// 获取构造函数
Constructor<IRouteRoot> constructor = clazz.getConstructor();
// 创建 IRouteRoot 类
IRouteRoot routeRoot = constructor.newInstance();
// 将 Root 表的信息装载到 Warehouse.groupsIndex 集合中
routeRoot.loadInto(Warehouse.groupsIndex);
// 打印 Root 表
for ( Map.Entry<String, Class<? extends IRouteGroup>> entry : Warehouse.groupsIndex.entrySet()){
Log.i(TAG, "loadInfo : " + entry.getKey() + " : " + entry.getValue().getName());
}
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
最终打印出的数据 :
loadInfo : kim.hsl.router_annotation.model.RouteBean$Type
loadInfo : kim.hsl.router.Router_Group_app
loadInfo : kim.hsl.router_annotation.Route
loadInfo : kim.hsl.router.Router_Root_library2
loadInfo : library2 : kim.hsl.router.Router_Group_library2
loadInfo : kim.hsl.router.Router_Root_app
loadInfo : app : kim.hsl.router.Router_Group_app
loadInfo : library2 : kim.hsl.router.Router_Group_library2
loadInfo : kim.hsl.router.Router_Group_library2
loadInfo : kim.hsl.router_annotation.model.RouteBean
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
获取了 “app” 分组的路由表 kim.hsl.router.Router_Group_app 类 ,
获取了 “library2” 分组的路由表 kim.hsl.router.Router_Group_library2 类 ,
已知路由表的类名 , 可以使用反射创建两个路由表 , 并拿到路由表中的数据 ;
四、Router 路由加载类代码
Router 现阶段完整代码 :
package kim.hsl.route_core;
import android.app.Application;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.os.Build;
import android.util.Log;
import java.io.IOException;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import dalvik.system.DexFile;
import kim.hsl.route_core.template.IRouteGroup;
import kim.hsl.route_core.template.IRouteRoot;
public class Router {
private static final String TAG = "Router";
/**
* 上下文
*/
private static Application mContext;
/**
* 单例类
*/
private static Router instance;
private Router() {
}
/**
* 初始化路由表
* @param application
*/
public static void init(Application application) {
mContext = application;
loadInfo();
}
/**
* 加载 分组 路由表 数据
* 每个分组对应一个路由表
*/
private static void loadInfo(){
/*
获取程序的所有 APK 安装文件
*/
ApplicationInfo applicationInfo = null;
try {
applicationInfo = mContext.getPackageManager().getApplicationInfo(mContext
.getPackageName(), 0);
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
}
// 使用集合存放应用安装的 APK 文件
List<String> sourcePaths = new ArrayList<>();
// 一般情况下 , 一个应用只有一个安装 APK
sourcePaths.add(applicationInfo.sourceDir);
// 如果是 instant run 形式安装的 , 则有多个 APK 文件
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
if (null != applicationInfo.splitSourceDirs) {
sourcePaths.addAll(Arrays.asList(applicationInfo.splitSourceDirs));
}
}
/*
根据获取所有 APK 下的类
根据 kim.hsl.router 包名, 获取该包名下的所有路由类
*/
// 获取查找的 kim.hsl.router 包下的类 的 类名
Set<String> classNames = new HashSet<>();
// 遍历所有的 APK 路径 , 查找其中的 DEX 中的类
for (final String path : sourcePaths) {
// 获取 APK 下的 dex 文件
DexFile dexfile = null;
try {
dexfile = new DexFile(path);
} catch (IOException e) {
e.printStackTrace();
}
Enumeration<String> dexEntries = dexfile.entries();
// 遍历 DEX 文件中的所有的类
while (dexEntries.hasMoreElements()) {
String className = dexEntries.nextElement();
if (className.startsWith("kim.hsl.router")) {
classNames.add(className);
}
}
}
// 最终所有的 kim.hsl.router 包下的类都存放到了 Set<String> classNames 变量中
for (String className : classNames){
/*
这是打印出来的类
kim.hsl.router_annotation.model.RouteBean$Type
kim.hsl.router.Router_Group_app
kim.hsl.router_annotation.Route
kim.hsl.router.Router_Root_library2
kim.hsl.router.Router_Root_app
kim.hsl.router.Router_Group_library2
kim.hsl.router_annotation.model.RouteBean
*/
Log.i(TAG, "loadInfo : " + className);
// 如果该类以 " Router_Root_ " 开头 , 说明这是 Root 表类
if (className.startsWith("kim.hsl.router.Router_Root_")) {
// root中注册的是分组信息 将分组信息加入仓库中
try {
// 获取 IRouteRoot 类
Class<IRouteRoot> clazz = (Class<IRouteRoot>) Class.forName(className);
// 获取构造函数
Constructor<IRouteRoot> constructor = clazz.getConstructor();
// 创建 IRouteRoot 类
IRouteRoot routeRoot = constructor.newInstance();
// 将 Root 表的信息装载到 Warehouse.groupsIndex 集合中
routeRoot.loadInto(Warehouse.groupsIndex);
// 打印 Root 表
for ( Map.Entry<String, Class<? extends IRouteGroup>> entry : Warehouse.groupsIndex.entrySet()){
Log.i(TAG, "loadInfo : " + entry.getKey() + " : " + entry.getValue().getName());
}
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
- 108
- 109
- 110
- 111
- 112
- 113
- 114
- 115
- 116
- 117
- 118
- 119
- 120
- 121
- 122
- 123
- 124
- 125
- 126
- 127
- 128
- 129
- 130
- 131
- 132
- 133
- 134
- 135
- 136
- 137
- 138
- 139
- 140
- 141
- 142
- 143
- 144
- 145
- 146
- 147
- 148
- 149
- 150
- 151
- 152
- 153
- 154
- 155
- 156
- 157
五、博客资源
博客源码 :
- GitHub : https://github.com/han1202012/Component
- CSDN 下载 :
文章来源: hanshuliang.blog.csdn.net,作者:韩曙亮,版权归原作者所有,如需转载,请联系作者。
原文链接:hanshuliang.blog.csdn.net/article/details/117255735
- 点赞
- 收藏
- 关注作者
评论(0)