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

自己动手,Android跨模块页面跳转Router方案_第1张图片

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

为什么要使用Router

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

方案思路

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

自己动手,Android跨模块页面跳转Router方案_第2张图片

代码实现

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

  • 在创建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方案)