ARouter使用简介_android

Paste_Image.png

 

上图是目前比较普遍使用的Android APP技术架构,往往是在一个界面中存在大量的业务逻辑,而业务逻辑中充斥着各种网络请求、数据操作等行为,整个项目中也没有模块的概念,只有简单的以业务逻辑划分的文件夹,并且业务之间也是直接相互调用、高度耦合在一起的;

 

ARouter使用简介_组件化_02

Paste_Image.png

 

上图单一工程模型下的业务关系,总的来说就是:你中有我,我中有你,相互依赖,无法分离。
然而随着产品的迭代,业务越来越复杂,随之带来的是项目结构复杂度的极度增加,此时我们会面临如下几个问题:

1、实际业务变化非常快,但是单一工程的业务模块耦合度太高,牵一发而动全身;
2、对工程所做的任何修改都必须要编译整个工程;
3、功能测试和系统测试每次都要进行;
4、团队协同开发存在较多的冲突.不得不花费更多的时间去沟通和协调,并且在开发过程中,任何一位成员没办法专注于自己的功能点,影响开发效率;
5、不能灵活的对业务模块进行配置和组装;

 

ARouter使用简介_android_03

Paste_Image.png

 

上图是组件化工程模型

ARouter使用简介_业务逻辑_04

Paste_Image.png

 

上图是组件化开发在Android studio里面的目录工程结构

ARouter使用简介_android_05

Paste_Image.png

 

这是组件化工程模型下的业务关系,业务之间将不再直接引用和依赖,而是通过“路由”这样一个中转站间接产生联系,我们今天要讲的就是这个路由。

路由怎么工作呢?
比如上面图中,每个业务分别在不同的moudle中,分别有ActivityA、ActivityB、ActivityC、ActivityD。
假如ActivityA想跳转到ActivityB怎么实现呢?通常跳转是这么写的:

 

Intent intent = new Intent(this,ActivityB.class);
startActivity(intent);

但是现在业务A和业务B在不同的moudle中,A业务中没法 import ActivityB,因为A和B是相互独立,没有依赖的。
路由做的事情就是在不用引导类的情况下实现这一跳转。

现在比较流行的路由有两个ActivityRouter、ARouter
ActivityRouter是个人项目
ARouter是阿里的项目
我们选择阿里的Arouter好一点

先看下ARouter的使用方法

 

android {
    defaultConfig {
    ...
    javaCompileOptions {
        annotationProcessorOptions {
        arguments = [ moduleName : project.getName() ]
        }
    }
    }
}

dependencies {
    // 替换成最新版本, 需要注意的是api
    // 要与compiler匹配使用,均使用最新版可以保证兼容
    compile 'com.alibaba:arouter-api:x.x.x'
    annotationProcessor 'com.alibaba:arouter-compiler:x.x.x'
    ...
}

然后在Application中初始化

 

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

接着使用注解标记要跳转的Activity

 

@Route(path = "/module_b/activity_b")
public class ActivityB extend Activity {
    ...
}

然后在ActivityA中这样跳转到ActivityB

 

ARouter.getInstance().build("/module_b/activity_b").navigation();

这样就完成了不同业务之间的跳转,是不是超级简单?

当然跳转一般都会传参数

 

// 2. 跳转并携带参数
ARouter.getInstance().build("/module_b/activity_b")
            .withLong("key1", 666L)
            .withString("key3", "888")
            .withObject("key4", new Test("Jack", "Rose"))
            .navigation();

在ActivityB中获取参数有两种方式,一种是普通Activity那样getIntent().getXXX
加一种是使用@Autowired注解的方式

 

@Route(path = "/test/activity")
public class Test1Activity extends Activity {
    @Autowired
    public String name;
    @Autowired
    int age;
    @Autowired(name = "girl") // 通过name来映射URL中的不同参数
    boolean boy;
    @Autowired
    TestObj obj;    // 支持解析自定义对象,URL中使用json传递

    @Override
    protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    ARouter.getInstance().inject(this);

    // ARouter会自动对字段进行赋值,无需主动获取
    Log.d("param", name + age + boy);
    }
}

还有一种情况,业务A是要使用业务C中的某个服务或者说某种功能,并不是想跳转Activity

这种情况下就要使用到IProvider

 

// 声明接口,其他组件通过接口来调用服务
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) {

    }
}

申明的接口放在base module中,接口的实现放在具体功能实现的module中。
然后在要使用这一服务的module中这样使用:

 

 HelloService helloService =   (HelloService) ARouter.getInstance().build("/service/hello").navigation();
 helloService.sayHello("Vergil");

这样就实现了调用其他业务服务

还有还可能通过ARouter获取其他业务模块的Fragment:

 

// 获取Fragment
Fragment fragment = (Fragment) ARouter.getInstance().build("/test/fragment").navigation();

下面是一些特殊用法:

 

// 构建标准的路由请求,startActivityForResult
// navigation的第一个参数必须是Activity,第二个参数则是RequestCode
ARouter.getInstance().build("/home/main", "ap").navigation(this, 5);

上面是从Activity调startActivityForResult 但是Arouter没有API支持从fragment调startActivityForResult
这种情况要怎么办呢?

可以这样做

 

 Postcard postcard = ARouter.getInstance().build("/module2/activity");
 LogisticsCenter.completion(postcard);
 Class<?> destination = postcard.getDestination();

这里得到的destination类就是我们要跳转的类,这样fragment的startActivityForResult就好办了

 

Intent intent = new Intent(getContext(),destination);
startActivityForResult(intent,requestCode);