【Android 组件化】路由组件 ( 运行时获取 注解处理器 生成的路由表 )

举报
韩曙亮 发表于 2022/01/10 23:18:24 2022/01/10
【摘要】 文章目录 一、获取应用的 APK二、获取所有 APK 中 kim.hsl.router 包的类三、获取其它 Module 中的路由表四、Router 路由加载类代码五、博客资源 组件化系...

在这里插入图片描述

组件化系列博客 :





一、获取应用的 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




五、博客资源



博客源码 :



在这里插入图片描述

文章来源: hanshuliang.blog.csdn.net,作者:韩曙亮,版权归原作者所有,如需转载,请联系作者。

原文链接:hanshuliang.blog.csdn.net/article/details/117255735

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。