IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 移动开发 -> 从零开始组件化(2)_路由跳转方式和手动搭建组件化路由 -> 正文阅读

[移动开发]从零开始组件化(2)_路由跳转方式和手动搭建组件化路由

在上一篇文章组件化-从零开始组件化(1)_z936689039的博客-CSDN博客中,我们已经搭建好整体框架了,然后问题就来了,因为组件化,各个业务组件是互相不依赖的,那假如涉及到跳转,我们应该怎么做呢,目前这块的做法有2种

1.隐式跳转

通过AndroidManifest中对要跳转的activity设置action值,然后跳转的时候,指定对应的action,从而实现跳转的,例如

在要隐式跳转的activity中配置:

//清单文件注册
<activity android:name=".MainActivity"
android:exported="false">
    <intent-filter>
        <action android:name="com.glde.dlr.module_main.MainActivity"/>
        <category android:name="android.intent.category.DEFAULT"/>
    </intent-filter>
</activity>

然后跳转到该activity:

           Intent intent=new Intent();
           intent.setAction("com.glde.dlr.module_main.MainActivity");
          if (LoginActivity.this.getPackageManager().resolveActivity(intent, PackageManager.MATCH_DEFAULT_ONLY) != null) {
                    intent.addCategory("android.intent.category.DEFAULT");
                    startActivity(intent);
                }

大概就这样子,但是问题也很明显吧,假如你们是2个团队开发,你这跳一个界面,就要人家配置androidManifest,别人肯定不乐意的,所以就有了下面更好的方案了

2.路由跳转

原理借用计算机网络中的路由器概念,将各组件看成不同的局域网,通过路由做中转站,这个中转站可以拦截一些不安全的跳转,或者设定一些特定的拦截服务;

路由和原生跳转的对比:
1. 原生显示跳转是直接的类依赖,耦合严重;路由通过URL索引,无需依赖;
2. 原生隐式跳转通过AndroidManifest集中管理,协作开发困难;路由则是分布式管理页面配置;
3. 原生需要在 AndroidManifest中注册,扩展性差;路由用注解来注册,方便扩展;
4. 原生只要调用了startActivity就交由Android系统控制,过程无法干预,失败无法降级;
路由使用AOP切面编程可以进行控制跳转的过滤,有灵活的降级方式;

阿里那边是开源了一款ARoute来实现这个功能,这个下篇文章在讲,这篇文章主要是为了阐述手动搭建路由框架的目的的,其实咱这个实现也简单,原理就是利用hashMap的存储功能去实现,因为业务组件模块不是都会关联个library_base,嗯,就这个基础库组件,那么我们就可以在这个里头创建个全局的HashMap,里头存储各个界面的路由不就行了,说搞就搞:

public class Aroute {
    private Context mContext;
    private static Map<String,Class<? extends Activity>> map;
    private static Aroute instance;
    public static Aroute getInstance(){
        if(instance==null){
            synchronized (Aroute.class){
                if(instance==null){
                    instance=new Aroute();
                }
                if(map==null){
                    map=new HashMap<>();
                }
            }
        }
        return instance;
    }
  
    public void putActivity(String activityName,Class cls){
        if(!TextUtils.isEmpty(activityName)&&null!=cls){
            map.put(activityName,cls);
        }
    }
    public void startActivity(String activityName, Bundle bundle,Context context){
        Class<? extends Activity> activity=map.get(activityName);
        if(null==activity){
            return;
        }
        Intent intent=new Intent(context,activity);
        if(null!=bundle){
            intent.putExtras(bundle);
        }
        intent.setFlags(FLAG_ACTIVITY_NEW_TASK);
        context.startActivity(intent);
    }
}

其中putActivity,你在要跳转的界面注册就好了,那么问题又来了,我们要跳转的时候,它那个界面还没实例化呀,也就是说根本注册不了,那么怎么办呢?

办法是有的, 我们将它提前编译,原理就是利用AMS中的相关知识点,我们都知道当我们在android Studio编译的时候会打包个apk到手机上,然后系统会创建个apk在用户的手机上,这个apk的路径地址为:

/data/app/app包名/base.apk

?这块对用户来说是不可见的,开发者们可以通过Android studio的Device File Explorer进行访问。

?然后当我们点击应用的时候,实际是加载解压这个文件里头的apk资源,那么就简单了,我们都知道apk实际是个压缩包来的,然后apk下面是好多个dex,其中dex里面是一堆class文件,对此我们就可以利用这点去提前获取到这些class,从而进行对业务组件进行注册

开搞

既然是利用它加载文件的特点的话,那么我们就可以这么做

1.先创建个接口,声明要跳转的界面和开放一个注册方法

public interface IRoute {
    String act_login="LoginActivity";
    String act_main="MainActivity";
    void onPut();
}

2.各个业务组件新建个目录,目录下创建个对象类去实现这个接口

public class LoginRoute implements IRoute {
    @Override
    public void onPut() {
        Aroute.getInstance().putActivity(IRoute.act_login, LoginActivity.class);
    }
}

?3.在app壳层的application中对这个Aroute进行初始化操作,初始化的时候,实际就是执行各个业务组件的onPut方法。具体做法是先通过

getActivityFromPackage获取base.apk下包名为com.glde.dlr.route的所有类集合,然后将它们加载进行内存,并且执行onPut方法
 public void init(Context context){
        mContext=context;
        //获取baseApk(android 打包后的apk)下对应包名为com.glde.dlr.route的所有类集合
        List<String> classNameList=getActivityFromPackage("com.glde.dlr.route");
        for(String className:classNameList){
            try {
                //将类装载进内存
                Class<?> cls= Class.forName(className);
                //判断转载进内存的类是否实现了IRoute接口
                if(IRoute.class.isAssignableFrom(cls)){
                    IRoute iRoute= (IRoute) cls.newInstance();//实例化对象向上转型为IRoute
                    iRoute.onPut();
                }
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (InstantiationException e) {
                e.printStackTrace();
            }
        }
    }
    public List<String>  getActivityFromPackage(String packgeName){
        List<String> classList=new ArrayList<>();
        try {
            //mContext.getPackageName()  获取  /data/app/对应包名下的base.apk的文件路径
            String path=mContext.getPackageManager().getApplicationInfo(mContext.getPackageName(),0).sourceDir;
            DexFile dexFile=new DexFile(path);//将baskapk 解压成dex,并且扫描apk中的dex有哪些类
            Enumeration<String> enumeration=dexFile.entries();//获取dexFail中所有类名
            //遍历dex所有类名
            while (enumeration.hasMoreElements()){
                //获取类名
                String className=enumeration.nextElement();
                if(className.startsWith(packgeName)){
                    classList.add(className);
                }
            }
        } catch (PackageManager.NameNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return classList;
    }
这样的话,就可以了

想要查看完整代码的可以去这里看GitHub - zhi936689039/ComponentizedDemo

  移动开发 最新文章
Vue3装载axios和element-ui
android adb cmd
【xcode】Xcode常用快捷键与技巧
Android开发中的线程池使用
Java 和 Android 的 Base64
Android 测试文字编码格式
微信小程序支付
安卓权限记录
知乎之自动养号
【Android Jetpack】DataStore
上一篇文章      下一篇文章      查看所有文章
加:2022-03-08 22:39:08  更:2022-03-08 22:39:30 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 17:10:20-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码