公司基本上都是独立完成的小项目,所以模块化开发没接触过,本着学习的精神看到了ARouter路由觉得还不错,简单学习下,在这里当做记笔记了。
在app moduel 下的build.gradle里添加:
defaultConfig {
……
……
//我添加的
javaCompileOptions {
annotationProcessorOptions {
arguments = [ moduleName : project.getName() ]
}
}
}
compile 'com.alibaba:arouter-api:1.2.1.1'
annotationProcessor 'com.alibaba:arouter-compiler:1.1.2.1'
tip:获取最新版本点我
初始化操作:
if (isDebug()) {
ARouter.openLog(); // 打印日志
ARouter.openDebug(); // 开启调试模式(如果在InstantRun模式下运行,必须开启调试模式!线上版本需要关闭,否则有安全风险)
}
ARouter.init(mApplication); // 尽可能早,推荐在Application中初始化
2.1 目标Activity
@Route(path = "/login/activity_1")
public class LoginActivity_1 extends AppCompatActivity {}
2.2.1 发起路由操作(不带参数)
ARouter.getInstance()
.build("/login/activity_1")
.navigation();
2.2.2 发起路由操作(带参数,如果是对象且需要实现Parcelable接口)
Bundle bundle = new Bundle();
Entity entity = new Entity("唐人", "m1234");
bundle.putParcelable("entity", entity);
ARouter.getInstance()
.build("/login/activity_1")
.withBoolean("state", false)
.withString("result", "123456")
.withParcelable("entity", entity)
.navigation();
2.3 目标Activity解析参数
2.3.1 使用原始getIntent()方式
Entity entity = getIntent().getParcelableExtra("entity");
boolean state = getIntent().getBooleanExtra("state",false);
……
……
2.3.2 使用ARouter协助解析参数类型
@Route(path = "/login/activity_1")
public class LoginActivity_1 extends AppCompatActivity {
@Autowired
public boolean state;//变量名与传参时一致且修饰符为public
@Autowired
public String result;
@Autowired
public Entity entity;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
ARouter.getInstance().inject(this);
TextView view = (TextView) findViewById(R.id.title);
view.setText(state + "\n" + result + "\n" + entity.toString());
}
}
声明拦截器,拦截器会在跳转之间执行,多个拦截器会按优先级顺序依次执行,init只在sdk初始化的时候才被调用仅1次
@Interceptor(priority = 100, name = "LoginCheck")
public class MyIInterceptor implements IInterceptor {
@Override
public void process(Postcard postcard, InterceptorCallback callback) {
switch (postcard.getPath()) {
case "/login/activity_1":
if (postcard.getExtras().getString("name").equals("wuxinxi"))
callback.onContinue(postcard);
else callback.onInterrupt(new RuntimeException("用户名不对哦"));
break;
default:
if (postcard.getExtra()==-100){
callback.onInterrupt(new RuntimeException("我看你不顺眼"));
}
callback.onContinue(postcard);
break;
}
}
@Override
public void init(Context context) {
System.out.println("拦截器被初始化");
}
}
通过Uri跳转
4.1 系统原生的方式:
<intent-filter>
<category android:name="android.intent.category.DEFAULT" />
<data
android:host="www.ccc"
android:port="80"
android:path="/app_name"
android:scheme="tangren" />
<action android:name="com.tangren" />
intent-filter>
java代码:
Intent intent = new Intent();
Uri uri = Uri
.parse("tangren://www.ccc:80/app_name");
intent.setData(uri);
intent.setAction("com.tangren");
try {
startActivity(intent);
} catch (Exception e) {
Toast.makeText(this, "找不到目标Activity", Toast.LENGTH_SHORT).show();
}
tip:
1.包含在 标签对里,而且是必不可少的!不管以哪一种方式来匹配,都不可缺少这个 ,可以有多个,至少要有一个,在代码中匹配data时可不匹配action也可启动目标Activity;
2.data中不能同时存在mineType、scheme;
3.根据action和data的mimeType属性匹配时,单靠data的mimeType属性不能匹配,就算这个mimeType是唯一的也不行,必须配合一个action ;
4.一个Activity里可以有多对 只要匹配其中一对,即可启动这个Activity
5. 任何一个需要隐式启动的Activity都必须要有这项:
例外情况是:android.intent.category.MAIN和android.intent.category.LAUNCHER
的filter中没有必要加入android.intent.category.DEFAULT,当然加入也没有问题
6. 当匹配不上任何Activity的话,会发生异常,记得捕获异常
4.2 ARouter
<intent-filter>
<data
android:host="com.tangren"
android:scheme="tangren"/>
<action android:name="com.tangren.action"/>
intent-filter>
java代码
Uri uri = Uri
.parse("tangren://com.tangren/login/activity_2");
ARouter.getInstance()
.build(uri)
.navigation();
html代码
<a href="tangren://com.tangren/login/activity_2">跳转a>
传递自定义对象点我
处理跳转结果
Uri uri = Uri
.parse("tangren://com.tangren/login/activity_2");
ARouter.getInstance()
.build(uri)
.navigation(this, new NavigationCallback() {
@Override
public void onFound(Postcard postcard) {
Toast.makeText(MainActivity.this, "发现目标Activity", Toast.LENGTH_SHORT).show();
}
@Override
public void onLost(Postcard postcard) {
Toast.makeText(MainActivity.this, "没有目标Activity", Toast.LENGTH_SHORT).show();
}
@Override
public void onArrival(Postcard postcard) {
Toast.makeText(MainActivity.this, "跳转完成", Toast.LENGTH_SHORT).show();
}
@Override
public void onInterrupt(Postcard postcard) {
Toast.makeText(MainActivity.this, "已被拦截", Toast.LENGTH_SHORT).show();
}
});
降级策略点我
为目标页面声明更多信息
// 我们经常需要在目标页面中配置一些属性,比方说"是否需要登陆"之类的
// 可以通过 Route 注解中的 extras 属性进行扩展,这个属性是一个 int值,换句话说,单个int有4字节,也就是32位,可以配置32个开关
// 剩下的可以自行发挥,通过字节操作可以标识32个开关,通过开关标记目标页面的一些属性,在拦截器中可以拿到这个标记进行业务逻辑判断
@Route(path = "/login/activity_3", extras = -100)
拦截器判断
if (postcard.getExtra()==-100){
callback.onInterrupt(new RuntimeException("我看你不顺眼"));
}
9.1 通过依赖注入解耦:服务管理-暴露服务
9.2 通过依赖注入解耦:服务管理-发现服务
详情点我
更多功能
10.1 初始化中的其他设置
ARouter.openLog(); // 开启日志
ARouter.openDebug(); // 使用InstantRun的时候,需要打开该开关,上线之后关闭,否则有安全风险
ARouter.printStackTrace(); // 打印日志的时候打印线程堆栈
10.2 详细的API说明
// 构建标准的路由请求
ARouter.getInstance().build("/home/main").navigation();
// 构建标准的路由请求,并指定分组
ARouter.getInstance().build("/home/main", "ap").navigation();
// 构建标准的路由请求,通过Uri直接解析
Uri uri;
ARouter.getInstance().build(uri).navigation();
// 构建标准的路由请求,startActivityForResult
// navigation的第一个参数必须是Activity,第二个参数则是RequestCode
ARouter.getInstance().build("/home/main", "ap").navigation(this, 5);
// 直接传递Bundle
Bundle params = new Bundle();
ARouter.getInstance()
.build("/home/main")
.with(params)
.navigation();
// 指定Flag
ARouter.getInstance()
.build("/home/main")
.withFlags();
.navigation();
// 获取Fragment
Fragment fragment = (Fragment) ARouter.getInstance().build("/test/fragment").navigation();
// 对象传递
ARouter.getInstance()
.withObject("key", new TestObj("Jack", "Rose"))
.navigation();
// 觉得接口不够多,可以直接拿出Bundle赋值
ARouter.getInstance()
.build("/home/main")
.getExtra();
// 转场动画(常规方式)
ARouter.getInstance()
.build("/test/activity2")
.withTransition(R.anim.slide_in_bottom, R.anim.slide_out_bottom)
.navigation(this);
// 转场动画(API16+)
ActivityOptionsCompat compat = ActivityOptionsCompat.
makeScaleUpAnimation(v, v.getWidth() / 2, v.getHeight() / 2, 0, 0);
// ps. makeSceneTransitionAnimation 使用共享元素的时候,需要在navigation方法中传入当前Activity
ARouter.getInstance()
.build("/test/activity2")
.withOptionsCompat(compat)
.navigation();
// 使用绿色通道(跳过所有的拦截器)
ARouter.getInstance().build("/home/main").greenChannel().navigation();
// 使用自己的日志工具打印日志
ARouter.setLogger();
10.3 获取原始的URI
String uriStr = getIntent().getStringExtra(ARouter.RAW_URI);
10.4 重写跳转URL
// 实现PathReplaceService接口,并加上一个Path内容任意的注解即可
@Route(path = "/xxx/xxx") // 必须标明注解
public class PathReplaceServiceImpl implements PathReplaceService {
/**
* For normal path.
*
* @param path raw path
*/
String forString(String path) {
return path; // 按照一定的规则处理之后返回处理后的结果
}
/**
* For uri type.
*
* @param uri raw uri
*/
Uri forUri(Uri uri) {
return url; // 按照一定的规则处理之后返回处理后的结果
}
}
https://github.com/alibaba/ARouter