路由框架ARouter使用及源码解析(一)
阅读原文时间:2021年04月21日阅读:2

系列文章:

路由框架ARouter使用及源码解析(一)
路由框架ARouter使用及源码解析(二)

文章目录

一、什么是路由?

路由是指路由器从一个接口上收到数据包,根据数据路由包的目的地址进行定向并转发到另一个接口的过程。—百度百科

以Android为例,各个组件module可以看成一个个网络,而路由就可以看成是各个模块页面跳转的中转站,除了中转以外,路由还可以过滤或拦截一些不安全或不规范的跳转。

二、阿里ARouter

官方定义:A framework for assisting in the renovation of Android componentization (帮助 Android App 进行组件化改造的路由框架)

其实Android的跳转已经提供了Intent,Intent不仅可以显示跳转,也可以隐式跳转。那么ARouter为什么还会存在呢?让我们对比一下原生跳转和路由跳转:
1、原生显示跳转必须依赖于类,强耦合,而隐式跳转需要都在AndroidManifest里集中注册,协作麻烦;而路由跳转通过URL索引,低耦合,协作方便;
2、原生在通过staryActivity启动跳转后就交由系统控制,并不能做拦截;路由跳转可以对跳转做过滤或拦截。

通过对比,我们发现路由特别适合用来做跳转(尤其是组件间的通信及跳转),下面就来看一下阿里ARouter的集成及使用吧~

2.1、配置&初始化

在app的build.config中配置:

compile 'com.alibaba:arouter-api:1.4.1'
annotationProcessor 'com.alibaba:arouter-compiler:1.2.2'

在各个需要使用ARouter模块的build.gradle的defaultConfig配置中加入:

javaCompileOptions {
    annotationProcessorOptions {
        arguments = [AROUTER_MODULE_NAME: project.getName()]
    }
}

注意:新版本已经改成AROUTER_MODULE_NAME来获取module名字了。

上面配置中,annotationProcessor用来声明注解解析器,arouter-compiler用来解析ARouter中的各个注解(后面会讲到),通过APT方式在编译期间自动生成class类,关于annotationProcessor可以查看下面这篇文章:
https://blog.csdn.net/xx326664162/article/details/68490059

配置完成后,进行初始化:

在自定义Application中进行初始化:

if (BuildConfig.DEBUG) {
    // 打印日志
    ARouter.openLog();
    // 开启调试模式(如果在InstantRun模式下运行,必须开启调试模式!线上版本需要关闭,否则有安全风险)
    ARouter.openDebug();
}
// 尽可能早,推荐在Application中初始化
ARouter.init(this);

初始化完成后,就可以开始使用了~

2.1、基本跳转

以Activity跳转为例,比如从Activity1跳转到Activity2,首先在1、目标Activity2中:

@Route(path = MConstant.ACTIVITY2)
public class Activity2 extends Activity {

}

Activity2添加注解@Route,path是跳转路径,一般都写在统一的一个类中,方便维护:

public class MConstant {
    public static final String ACTIVITY2 = "/main/activity2";
    public static final String TRANSFER_KEY = "transfer_key";
}

2、在Activity1中进行ARouter注入并实现跳转:

public class Activity1 extends Activity {

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

        findViewById(R.id.button).setOnClickListener(new View.OnClickListener() {
          @Override
          public void onClick(View v) {
              ARouter.getInstance().build(MConstant.ACTIVITY2).navigation();
          }
         });

    }

上面就实现了简单的页面跳转,如果想传递参数,可以用下面的方式:

ARouter.getInstance().build(path).withString(MConstant.TRANSFER_KEY,"value").navigation();

withXXX处填的是参数的key和value (如果ARouter传递的是对象,首先该对象需要Parcelable或者Serializable序列化) ,navigation发射了路由跳转。在目标类中,通过注解@Autowired来获取传递值:

public class Activity2 extends Activity {

    @Autowired(name = TRANSFER_KEY)
    public String qrText;
}

2.3、获取Fragment实例

首先在Fragment上使用注解@Route

@Route(path = "/test/fragment")
public class BlankFragment extends Fragment {
}

获取Fragment实例:

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

通过上面的代码就可以获取Fragment的实例,这在跨模块中使用Fragment是很有用的。

2.4、进阶用法之拦截器&通过URL跳转

拦截器:

@Interceptor(priority = 1)
public class MyInterceptor implements IInterceptor {

    private Context context;

    @Override
    public void process(Postcard postcard, InterceptorCallback callback) {
        if (MConstant.ACTIVITY2.equals(postcard.getPath())) {
            //如果是跳转Activity2,则拦截
            callback.onInterrupt(null);
        } else {
            callback.onContinue(postcard);
        }
    }

    @Override
    public void init(Context context) {
        this.context = context;
    }
}

拦截器需要实现IInterceptor并通过注解@Interceptor来声明,其中多个拦截器的优先级根据priority来判断,值越小优先级越高。

通过URL跳转:

Uri testUriMix = Uri.parse("arouter://m.aliyun.com/main/activity2");
ARouter.getInstance().build(testUriMix)
        .withString("key1", "value1")
        .navigation();

跟上面介绍的普通跳转几乎一样,上面是用的path跳转,而这里使用的是URL跳转,一般在自定义协议(如webview)时,使用URL跳转非常的方便,并且可以对URL做拦截、转换等。

2.5、服务管理

比如ModuleA中想调用ModuleB中的方法,在公共引用库中声明接口并继承IProvider:

public interface IModuleService extends IProvider {

    String getModuleName();
}

在ModuleB中定义接口实现类:

@Route(path = MConstant.MODULE_SERVICE)
public class ChatModuleService implements IModuleService {
    @Override
    public String getModuleName() {
        return "chatModule";
    }

    @Override
    public void init(Context context) {

    }
}

在ModuleA中调用:

//1、通过类名调用服务
IModuleService service = ARouter.getInstance().navigation(IModuleService.class);
String getName = service.getModuleName();
Log.e("TTT", "getName is " + getName);

//2、通过路径名称调用服务
IModuleService service1 = (IModuleService) ARouter.getInstance().build(MConstant.MODULE_SERVICE).navigation();
String getName1 = service1.getModuleName();
Log.e("TTT", "getName1 is " + getName1);

上面两种方式都可以最终得到ModuleB中的数据。

2.6、降级方案

ARouter.getInstance().build("/xxx/xxx").navigation(this, new NavCallback() {
    @Override
    public void onFound(Postcard postcard) {
        Log.d("ARouter", "找到了");
    }

    @Override
    public void onLost(Postcard postcard) {
        Log.d("ARouter", "找不到了");
    }

    @Override
    public void onArrival(Postcard postcard) {
        Log.d("ARouter", "跳转完了");
    }

    @Override
    public void onInterrupt(Postcard postcard) {
        Log.d("ARouter", "被拦截了");
    }
});

当跳转失败时,可以通过回调得到结果并做相应处理。

三、引用

【1】ARouter: https://github.com/alibaba/ARouter
【2】APT、annotationProcessor、android-apt、Provided、自定义注解:
https://blog.csdn.net/xx326664162/article/details/68490059

手机扫一扫

移动阅读更方便

阿里云服务器
腾讯云服务器
七牛云服务器

你可能感兴趣的文章