Android路由框架-ARouter详解
文章大纲
一、页面路由基本介绍
1.什么是页面路由
2.为什么要使用页面路由
二、页面路由框架ARouter介绍
1.常用功能介绍
2.常见应用场景
三、源码下载
四、参考文章
一、页面路由基本介绍
1.什么是页面路由
映射页面跳转关系,包含跳转相关的URL跳转及值传递、拦截器等功能。
2.为什么要使用页面路由
在原始android开发中,当我们需要进行页面跳转时,正常写法如下:
Intent intent = new Intent(mContext, XXActivity.class);
intent.putExtra("key","value");
startActivity(intent);
Intent intent = new Intent(mContext, XXActivity.class);
intent.putExtra("key","value");
startActivityForResult(intent, 100);
上述写法容易出现以下问题:
- 多人协同开发的时候,大家都去AndroidManifest.xml中定义各种IntentFilter,使用隐式Intent,最终发现AndroidManifest.xml中充斥着各种Schame,各种Path,需要经常解决Path重叠覆盖、过多的Activity被导出,引发安全风险等问题
- 跳转过程中无法插手:直接通过Intent的方式跳转,跳转过程开发者无法干预,一些面向切面的事情难以实施,比方说登录、埋点这种非常通用的逻辑,在每个子页面中判断又很不合理,毕竟activity已经实例化了
- 跨模块无法显式依赖:在App小有规模的时候,我们会对App做水平拆分,按照业务拆分成多个子模块,之间完全解耦,通过打包流程控制App功能,这样方便应对大团队多人协作,互相逻辑不干扰,这时候只能依赖隐式Intent跳转,书写麻烦,成功与否难以控制
页面路由可以解决什么问题?
二、页面路由框架ARouter介绍
1.常用功能介绍
应用内页面跳转
添加依赖
温馨提示:api 的版本和 compiler 的版本号需要用最新的。最新的版本在 Github上可以找到。
重写Application并初始化ARouter
配置将要跳转的页面
进行简单的页面跳转
温馨提示:如果你想实现像 startActivityForResult() 功能,可以这样使用
运行结果如下:
携带参数进行页面跳转
温馨提示:支持数据类型如下:
运行程序,结果如下图所示:
路由监听
在路由跳转的过程中,我们可以监听路由的过程,只需要以下使用:
navigation(Context context, NavigationCallback callback)
NavigationCallback 的源码如下:
public interface NavigationCallback {
添加用于测试跳转的页面
在跳转的页面中添加监听代码
运行结果如下:
拦截器使用
添加需要跳转的页面
添加拦截器
在主页面进行跳转拦截测试
路由分组
在前面我们讲到在对 Activity1 做注解的时候,用到了
@Route(path = "/com/Activity1")
public class Activity1 extends AppCompatActivity {}
在 path 这个字符串里面,”com” 就代表组的标识;“Activity1” 代表是 Activity1 类的具体表示。组的标识和类的标识都可以自己定义的,需要记住的是组标识和类标识之间用斜杠来区分 ”\” .
什么是组?
这里就需要提下,ARouter框架是分组管理,按需加载。提起来很高深的样子呢!其实解释起来就是,在编译期框架扫描了所有的注册页面/服务/字段/拦截器等,那么很明显运行期不可能一股脑全部加载进来,这样就太不和谐了。所以就分组来管理,ARouter在初始化的时候只会一次性地加载所有的root结点,而不会加载任何一个Group结点,这样就会极大地降低初始化时加载结点的数量。比如某些Activity分成一组,组名就叫test,然后在第一次需要加载组内的某个页面时再将test这个组加载进来。
测试一下:
ARouter.getInstance()
.build("/wxc/Activity1")
.navigation(this, new NavCallback() {
@Override
public void onArrival(Postcard postcard) {
String group = postcard.getGroup();
Log.e("zhao", "分组是: " + group);
}
});
结果是
07-27 17:32:17.880 19449-19449/com.router E/zhao: 分组是: wxc
ARouter 默认情况下的分组就是第一个 / / 之间的内容。
自定义分组
创建 CustomGroupActivity 并且添加 注解,并且指定路由分组。自定义分组的就是在原来的注解上添加 group 字段, 如下所示。
@Route(path = "/com/CustomGroupActivity" , group = "customGroup")
public class CustomGroupActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_custom_group);
}
}
自定义分组,发起路由:第二个参数就是路由的分组
build(String path, String group)
具体实现如下所示:
ARouter.getInstance().build("/com/CustomGroupActivity", "customGroup").navigation();
URL 跳转
web url 跳转流程图
创建URL 中间跳转页
创建 URLReceiveActivity
URLReceiveActivity 添加注册
<activity android:name=".URLReceiveActivity">
这里面的 host 、scheme 字段很重要。点击 url 会根据这两个字段会调起本地的 Activity 。
下面是一段 HTML 片段
<h2>1:URL普通跳转</h2>
<p><a href="arouter://zhaoyanjun/com/URLActivity1">arouter://zhaoyanjun/com/URLActivity1 </a>
</p>
<h2>2:URL普通跳转携带参数</h2>
<p>
<a href="arouter://zhaoyanjun/com/URLActivity2?name=alex&age=18&boy=true&high=180&obj=%7b%22name%22%3a%22jack%22%2c%22id%22%3a666%7d">arouter://zhaoyanjun/test/URLActivity2?name=alex&age=18&boy=true&high=180&obj={"name":"jack","id":"666"}
</a>
</p>
注意 a 标签里面的 arouter://zhaoyanjun 分别代表着 scheme 、host ;/com/URLActivity1 就是目标 Activity 的注解。
如果需要接收 URL 中的参数,需要在 Activity 调用自动注入初始化方法;
ARouter.getInstance().inject(this);
需要注意的是,如果不使用自动注入,那么可以不写 ARouter.getInstance().inject(this),但是需要取值的字段仍然需要标上 @Autowired 注解,因为 只有标上注解之后,ARouter才能知道以哪一种数据类型提取URL中的参数并放入Intent中,这样您才能在intent中获取到对应的参数
具体的代码如下:
@Route(path = "/com/URLActivity2")
public class URLActivity2 extends AppCompatActivity{
private TextView textView;
@Autowired
String name;
@Autowired
int age;
@Autowired
boolean boy;
@Autowired
int high;
@Autowired
String obj ;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ARouter.getInstance().inject(this);
setContentView(R.layout.activity_url2);
textView = (TextView) findViewById(R.id.tv);
效果图如下:
暴露服务
这里说到的服务不是Android四大组件中的Service,这里的服务是接口开发的概念,就是将一部分功能和组件封装起来成为接口,以接口的形式对外提供能力,所以在这部分就可以将每个功能作为一个服务,而服务的实现就是具体的业务功能。
我们先自定义一个接口 IService 并且继承 IProvider 。IService 接口里面有一个 sayHello() 方法,具体代码如下。
public interface IService extends IProvider {
void sayHello(Context context );
}
先定义一个 IService 的实现类 MyService 并且添加注解,代码如下
@Route(path = "/service/hello", name = "测试服务")
public class MyService implements IService {
@Override
public void sayHello( Context context ) {
Toast.makeText( context , "hello", Toast.LENGTH_SHORT).show();
}
@Override
public void init(Context context) {
}
}
发现服务,首先定义服务对象,并且添加注解,我们不需要知道接口的具体实现类。
@Autowired(name = "/service/hello")
IService service;
然后添加注解初始化,自动赋值。
ARouter.getInstance().inject(this);
最后我们调用 service 里面的 sayHello() 方法。
service.sayHello(this);
发现服务这个功能的特点在于,我们只需要知道接口,不需要关心接口的实现类,很好了实现了解耦。
路由关闭
ARouter.getInstance().destroy();
温馨提示:该功能慎用,搞不好整个app页面跳转就gg了。
代码混淆
如果我们使用了Proguard进行代码混淆,可以添加以下代码
-keep public class com.alibaba.android.arouter.routes.**{*;}
-keep class * implements com.alibaba.android.arouter.facade.template.ISyringe{*;}
2.常见应用场景
- 从外部URL映射到内部页面,以及参数传递与解析
说明:该场景使用到了该文章的URL跳转和暴露服务功能,这样使得页面跳转功能很好的解耦,特别对于团队开发有很好管理作用。
- 跨模块页面跳转,模块间解耦
- 处理登陆、埋点等逻辑
说明:该场景使用到了路由监听和拦截跳转等功能,在原始处理登陆、埋点等功能中,我们会先初始化Activity,再进行逻辑判断,这样会影响性能,如果我们使用了监听和拦截,那么在初始化新的Activity之前,我们可以先进行逻辑判断。
三、源码下载
链接:https://pan.baidu.com/s/1Y7Br3iKlDb-55VG1kAU70A
提取码:m0at
四、参考文章
- https://www.cnblogs.com/zhujiabin/p/7193400.html
- https://blog.csdn.net/x605940745/article/details/80583912
- https://blog.csdn.net/zhaoyanjun6/article/details/76165252