97

Android点我达路由DRouter框架设计与解析

 5 years ago
source link: http://tech.dianwoda.com/2018/09/30/androiddian-wo-da-lu-you-drouterkuang-jia-jie-xi/?amp%3Butm_medium=referral
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

为什么要路由

什么是路由?说简单点就是映射页面跳转关系的,当然它也包含跳转相关的一切功能。Android系统已经给我们提供了api来做页面跳转,比如startActivity,为什么还需要路由框架呢?我们来简单分析下路由框架存在的意义:

  • 在一些业务场景下,灵活性比较强,很多功能都是运营人员动态配置的,比如下发一个活动页面,我们事先并不知道具体的目标页面,但如果事先做了约定,提前做好页面映射,便可以自由配置。
  • 随着业务量的增长,项目越来越庞大,开发人员越来越多,App一般都会走向组件化、插件化的道路;而组件化、插件化的前提就是解耦,那么我们首先要做的就是解耦页面之间的依赖关系。
  • 极大简化代码。数行跳转代码可以精简成一行代码。

因此我们设计了一个路由框架我们命名为DRouter。总的来说,DRouter设计追求的是功能模块的解耦,能够实现基本路由功能,以及开发者使用上足够简单。DRouter对于使用者来说几乎是无成本的,只需要在使用路由的页面定义一个类注解@DRoute即可,页面路由的使用也相当简单。

DRouter的特性

  • 链式调用设计,写法简单;
  • 使用编译时处理注解生成路由映射表,性能优于运行时处理编译的路由方案;
  • 路由url的设计与常规的http url一致,可以通过query参数传递页面参数;
  • 支持通过注解直接注入跳转参数;
  • 支持多个路由url跳转至同一个页面;
  • 支持路由的正则匹配;
  • 支持Activity启动使用不同的Flag;
  • 支持路由的优先级配置;
  • 支持对路由的动态拦截、监听以及降级;
  • 后期将增加action支持,支持通过一个Router链接执行一个方法;

关于DRouter的设计

DRouter URI定义

对于DRouter URI的定义为了使用起来更自然,我们选择模仿HTTP URI协议: JFJbuaq.png!web * Scheme的定义目前我们支持dwd、dwd-rider、dwd-shop,当然之后有其它端需要接入时,可以自定义拓展; * Host我们定义了view、action,其中view表示这个是一个页面跳操作,action表示执行一个method; * Path则是与路由表对应,表示一个页面或方法; * Query参数与传统的http get query参数一致,支持拼接基础数据类型、String、JSON串;

DRouter 执行流程

fm6zYv3.png!web * 根据解析传入的DRouter URI创建DRouteRequest对象,并且set调用者传入的callback、flags、requestCode、extras等; * 判断是否有设置拦截器,如果有设置拦截器则进行执行拦截器方法,本次DRouter执行流程结束,通知调用者本次请求被拦截; * 如果没有拦截器,则与路由表中的path进行匹配,如果匹配通过则Intent构建; * 将参数put到构建完成的Intent中传到目标页面;

DRouter的使用

接下来我们来实战一番,一个Android项目怎么接入这个DRouter框架,完成路由的生成、跳转、拦截器的使用等流程。

集成

在工程根目录的build.gradle中加入:

allprojects {
   repositories {
      maven { url "http://192.168.1.31:8081/repository/lib-dwd-snapshots/"}
      maven { url "http://192.168.1.31:8081/repository/lib-dwd-releases/"}
}}

在需要使用module build.gradle中加入:

defaultConfig {
    javaCompileOptions {
        annotationProcessorOptions {
            arguments = ["moduleName": project.name]
        }
    }
}

dependencies {
   compile 'com.dwd.drouter:routercenter:1.0.1'
   annotationProcessor 'com.dwd.drouter:compiler:1.0.0'
}

OK,这样你的工程里面就可以使用DRouter了;

使用

一行代码完成各种复杂的跳转:

DRouter.with(context).load(uri).extra("name","张三").launch();

链式api,清晰明了,使用简单,当然要达到这么有B格的跳转还是得先做点基建工作;

1、初始化DRouter

在你的Application中的onCreate方法中加入:

public void onCreate() {
   //这里要加入所有使用DRouter的module name
   DRouter.init("module1", "module2", ...);
}

2、通过注解创建路由表

在你需要Router化的页面使用@DRoute(path="/main")注解来为这个页面在路由表创建一个path:

@DRoute(path="/main")
public class MainActivity extends Activity{
   @override
   public void onCreate(Bundle args) {
       super.onCreate(args);
   }
}

没错,只要这么一个注解,你这个页面就完成Router化了;

3、创建并使用interceptor

在很多时候,我们在打开一个页,必须先登陆,这个时候我们总不可能在每次跳转一个页面前先判断一下是否登陆、执行登陆逻辑,因此我们就引入拦截器,那么怎么创建interceptor呢?也很简单:

@Interceptor("login")
public class LoginInterceptor implements DRouteInterceptor{
    @Override
    public boolean intercept(@Nullable Object source, DRouteRequest routeRequest) {
        if (source instanceof Context && !BaseApplication.getInstance().isLogin()) {
            DRouter.with((Context) source)
                    .load(Uri.parse("dwd://view/login"))
                    .extra("routerUrl", routeRequest.getUri().toString())
                    .launch();
            return true;
        }
        return false;
    }
}

这是一个比较典型的登陆interceptor,逻辑很简单,就是判断是否有登陆,如果没有登陆,就跳转到登陆界面,并且目标页面的routerUrl传递过去,使得登陆成功后可以继续跳转到目标页面,然后return true表示这个router跳转被拦截了;

那么interceptor创建好之后怎么使用它呢?其实也很简单,只需要在DRoute注解的interceptor参数中设置好你的登陆interceptor即可:

@DRoute(path="/main", interceptor="login")
public class MainActivity extends Activity{
   @override
   public void onCreate(Bundle args) {
       super.onCreate(args);
   }
}

4、通过注解注入参数

一般跳转到一个页面都是需要传入参数的,使用DRouter你可以直接使用注解注入参数,所有的参数DRouter会通过编译时处理注解方式自动注入到目标页面,在不降低性能的情况下极大减少了你的代码量,具体用法如下:

@DRoute(path="/main", interceptor="login")
public class MainActivity extends Activity{
   @Param(key = "name")
   String name;

   @override
   public void onCreate(Bundle args) {
       super.onCreate(args);
       DRouter.injectParams(this);
   }
}

总结

DRouter目前是一个很轻巧、简单、清晰的路由框架、可以将Push、Weex、H5与Native端之间的相互跳转无缝的整合在一起,当然目前也存在很多待优化的地方,我也会逐步的去优化完善它。


Recommend

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK