ARouter简单入门和介绍

作者: Mapleslong | 来源:发表于2017-10-25 19:04 被阅读751次

    1.路由介绍

    什么是路由框架?

    说简单点就是映射页面跳转关系的,当然它也包含跳转相关的一切功能

    为什么使用ARouter?

    我们先从适用场景来分析:

    1. 动态跳转:一般来说复杂的电商跳转多页面需要很强的灵活性,很多情况下是运营人员动态配置的下发活动页面,需要灵活的进行跳转。

    2. 组件化:随着业务量的不断增长,app也会不断的膨胀,开发团队的规模和工作量也会逐渐增大,面对所衍生的64K问题、协作开发问题等,app一般都会走向组件化。组件化就是将APP按照一定的功能和业务拆分成多个组件module,不同的组件独立开发,组件化不仅能够提供团队的工作效率,还能够提高应用性能。而组件化的前提就是解耦,那么我们首先要做的就是解耦页面之间的依赖关系

    3. Native与H5的问题:现在的APP很少是纯Native的,也很少会有纯H5的,一般情况下都是将两者进行结合。这时候就需要非常便捷并且统一的跳转方案,因为在H5中是无法使用StartActivity()跳转到Native页面的,而从Native跳转到H5页面也只能通过配置浏览器的方式实现

    4. 其他等场景

    原生跳转方式的不足

    • 显式跳转, Intent intent = new Intent(activity, XXActivity.class);
      由于需要直接持有对应class,从而导致了强依赖关系,提高了耦合度
    • 隐式跳转,譬如 Intent intent = new Intent(); intent.setAction(“com.android.activity.MY_ACTION”);
      action等属性的定义在Manifest,导致了扩展性较差
      规则集中式管理,导致协作变得非常困难。
    • 原生的路由方案会出现跳转过程无法控制的问题,因为一旦使用了StartActivity()就无法插手其中任何环节了,只能交给系统管理,这就导致了在跳转失败的情况下无法降级,而是会直接抛出运行时的异常。

    2.ARouter的使用

    1.添加框架的依赖和配置

    在各个模块的build.gradle中添加编译参数和依赖的框架

    android {
        defaultConfig {
        ...
        javaCompileOptions {
            annotationProcessorOptions {
            arguments = [ moduleName : project.getName() ]
            }
        }
        }
    }
    
    dependencies {
        // 替换成最新版本, 需要注意的是api
        // 要与compiler匹配使用,均使用最新版可以保证兼容
        compile 'com.alibaba:arouter-api:1.2.2'
        annotationProcessor 'com.alibaba:arouter-compiler:1.1.3'
        ...
    }
    
    // 旧版本gradle插件(< 2.2),可以使用apt插件,在根build.gradle中配置方法
    apply plugin: 'com.neenbedankt.android-apt'
    
    buildscript {
        repositories {
            jcenter()    
        }
    
        dependencies {
        classpath 'com.neenbedankt.gradle.plugins:android-apt:1.4'
        }
    }
    

    2.添加注解

    // 在支持路由的页面上添加注解(必选)
    // 这里的路径需要注意的是至少需要有两级,/xx/xx
    @Route(path = "/test/activity")
    public class YourActivity extend Activity {
        ...
    }
    

    3.初始化SDK

    if (isDebug()) {           // 这两行必须写在init之前,否则这些配置在init过程中将无效
        ARouter.openLog();     // 打印日志
        ARouter.openDebug();   // 开启调试模式(如果在InstantRun模式下运行,必须开启调试模式!线上版本需要关闭,否则有安全风险)
    }
    ARouter.init(mApplication); // 尽可能早,推荐在Application中初始化
    

    4.路由操作

    // 1.普通跳转
    ARouter.getInstance().build("/test/activity").navigation();
    
    // 2.跳转并携带参数
    ARouter.getInstance().build("/test/activity2").navigation();
    // 3.跳转并携带请求码
    ARouter.getInstance().build("/test/activity2").navigation(this, requestCode);
    
    // 4.URI跳转 
    /*这种使用URi的方式中,URi的Scheme 和 host不影响结果,可以随便设,关键的是path
    *  - build(URI)会把URI解析为path,并把当前URI存入PostCard
    *  - build(String)构造的PostCard不存储URI*/
    Uri testUriMix = Uri.parse("xx://xxx/test/activity2");
    ARouter.getInstance().build(testUriMix)
                            .withString("name", "老王")
                            .withInt("age", 18)
                            .withBoolean("boy", true)
                            .withLong("high", 180)
                            .withString("url", "https://a.b.c")
                            .withParcelable("pac", testParcelable)
                            .withObject("obj", testObj)
                            .navigation();
    
    // 5.跳转包含回调 单次降级策略可以在这里使用
    ARouter.getInstance().build("/test/activity2").navigation(Context mContext, int requestCode, NavigationCallback callback);
    

    5.配置自定义序列化方式

    上诉的代码中有withObject进行传参,没有定义序列化方式是无法进行解析因此需要定义一个序列化方式,以下采用FastJson进行序列化

    // 如果需要传递自定义对象,需要实现 SerializationService,并使用@Route注解标注(方便用户自行选择序列化方式),例如:
    @Route(path = "/service/json")
    public class JsonServiceImpl implements SerializationService {
        @Override
        public void init(Context context) {
    
        }
    
        @Override
        public <T> T json2Object(String text, Class<T> clazz) {
            return JSON.parseObject(text, clazz);
        }
    
        @Override
        public String object2Json(Object instance) {
            return JSON.toJSONString(instance);
        }
    }
    

    6.声明拦截器(拦截跳转过程,面向切面编程)

    // 比较经典的应用就是在跳转过程中处理登陆事件,这样就不需要在目标页重复做登陆检查
    // 拦截器会在跳转之间执行,多个拦截器会按优先级顺序依次执行
    @Interceptor(priority = 8, name = "测试用拦截器")
    public class TestInterceptor implements IInterceptor {
        @Override
        public void process(Postcard postcard, InterceptorCallback callback) {
        ...
        callback.onContinue(postcard);  // 处理完成,交还控制权
        // callback.onInterrupt(new RuntimeException("我觉得有点异常"));      // 觉得有问题,中断路由流程
    
        // 以上两种至少需要调用其中一种,否则不会继续路由
        }
    
        @Override
        public void init(Context context) {
        // 拦截器的初始化,会在sdk初始化的时候调用该方法,仅会调用一次
        }
    }
    

    // 我们经常需要在目标页面中配置一些属性,比方说"是否需要登陆"之类的
    // 可以通过 Route 注解中的 extras 属性进行扩展,这个属性是一个 int值,换句话说,单个int有4字节,也就是32位,可以配置32个开关
    // 剩下的可以自行发挥,通过字节操作可以标识32个开关,通过开关标记目标页面的一些属性,在拦截器中可以拿到这个标记进行业务逻辑判断
    @Route(path = "/test/activity", extras = Consts.XXXX)

    7.通过依赖注入解耦:服务管理(一) 暴露服务

    // 声明接口,其他组件通过接口来调用服务
    public interface HelloService extends IProvider {
        String sayHello(String name);
    }
    
    // 实现接口
    @Route(path = "/service/hello", name = "测试服务")
    public class HelloServiceImpl implements HelloService {
    
        @Override
        public String sayHello(String name) {
        return "hello, " + name;
        }
    
        @Override
        public void init(Context context) {
    
        }
    }
    

    8.通过依赖注入解耦:服务管理(二) 发现服务

    public class Test {
        @Autowired
        HelloService helloService;
    
        @Autowired(name = "/service/hello")
        HelloService helloService2;
    
        HelloService helloService3;
    
        HelloService helloService4;
    
        public Test() {
        ARouter.getInstance().inject(this);
        }
    
        public void testService() {
         // 1. (推荐)使用依赖注入的方式发现服务,通过注解标注字段,即可使用,无需主动获取
         // Autowired注解中标注name之后,将会使用byName的方式注入对应的字段,不设置name属性,会默认使用byType的方式发现服务(当同一接口有多个实现的时候,必须使用byName的方式发现服务)
        helloService.sayHello("Vergil");
        helloService2.sayHello("Vergil");
    
        // 2. 使用依赖查找的方式发现服务,主动去发现服务并使用,下面两种方式分别是byName和byType
        helloService3 = ARouter.getInstance().navigation(HelloService.class);
        helloService4 = (HelloService) ARouter.getInstance().build("/service/hello").navigation();
        helloService3.sayHello("Vergil");
        helloService4.sayHello("Vergil");
        }
    
    

    小结

    官方的文档Github很详细可以去看看

    以上方式可以进行简单的入门使用了,下一步我们从源码分析。

    相关文章

      网友评论

        本文标题:ARouter简单入门和介绍

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