美文网首页自定义views Android知识Android开发经验谈
自己动手,Android跨模块页面跳转Router方案

自己动手,Android跨模块页面跳转Router方案

作者: 让我来试试 | 来源:发表于2017-07-31 18:32 被阅读1960次

    在引入多模块开发后,我们首先要解决的就是模块间页面跳转的问题。本文意在提供一种思路而非框架。

    为什么要使用Router

    我们知道,Google SDK提供了显式和隐式两种原生路由方案。但在模块化开发中,显式Intent存在类直接依赖的问题,造成模块间严重耦合。隐式Intent则需要在Manifest中配置大量路径,导致难以拓展(如进行跳转拦截)。为了解决以上问题,我们需要采用一套更为灵活的Router方案。

    方案思路

    我们的思路很简单,使用注解,为每个activity类标注别名。在启动时对类进行扫描,将带有注解的activity存放路由表中。整个过程被我们封装在ActionManager类中,并对外暴露startAction(String alias ,Bundle data)接口,跳转时通过别名在路由表中进行匹配,完成跳转。大致流程如下:

    代码实现

    以下是我截取的代码片段,方便大家理解,

    • 在创建Activity时,通过注解,为其注释别名:
    @Action("loginActivity ")
    public class LoginActivity extends BaseBase{
            //代码省略...
    }
    
    • 在启动时(Application类中),对包下的所有类进行扫描,将带有注解标注的Activity,存入map,代码如下:
    private void activityScan(Context ctx) {
            try {
                //通过资源路径获得DexFile
                DexFile e = new DexFile(ctx.getPackageResourcePath());
                Enumeration entries = e.entries();
                //遍历所有元素
                while(entries.hasMoreElements()) {
                    String entryName = (String)entries.nextElement();
                    //匹配Activity包名
                    if(entryName.contains("activity")) {
                        //通过反射获得Activity类
                        Class entryClass = Class.forName(entryName);
                        if(entryClass.isAnnotationPresent(Action.class)) {
                            Action action = (Action)entryClass.getAnnotation(Action.class);
                            this.mapping.put(action.value(), entryClass.getName());
                        }
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
    
        }
    
    • 对外暴露接口,提供根据别名跳转Activity的方法:
    ActionManager.getInstance().startAction(currentActivity.this ,"loginActivity ");
    

    我们可以请求方法中做一些拦截处理,同样可以通过Bundle传输数据。以下是startAction方法的实现:

    public void startAction(Activity original, String alias) throws ClassNotFoundException {
            if(this.mapping.containsKey(alias)) {
                Intent intent = new Intent(original, Class.forName((String)this.mapping.get(alias)));
                original.startActivity(intent);
            } else {
                throw new ClassNotFoundException();
            }
    }
    

    我们通过这种方式,解决了跳转Activity所产生的的模块依赖问题,相较于原生方案,拓展性更强。但这种方案只是阶段性的,还存在一些问题。首先,加载过程中,频繁使用到反射,会产生性能问题。其次,对于每个Activity的别名,需要进行统一维护,增加了协作成本。对此,我们正在尝试使用APT工具改进,目的是让扫描过程在编译期完成,避免运行时加载。

    期望

    目前市场上有不少Router框架,秉承不重复造轮子的原则,我们可以在项目中直接使用。但如开篇所述,我们意在提供一种思路,记录演进过程,框架是别人的,思路是自己的,只有这样才能形成对自己有益的技术栈。

    相关文章

      网友评论

        本文标题:自己动手,Android跨模块页面跳转Router方案

        本文链接:https://www.haomeiwen.com/subject/gzwllxtx.html