Android模块化开发--路由ARouter日常使用
概述
公司基本上都是独立完成的小项目,所以模块化开发没接触过,本着学习的精神看到了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:获取最新版本点我
日常使用
step.1
初始化操作:
if (isDebug()) { ARouter.openLog(); // 打印日志 ARouter.openDebug(); // 开启调试模式(如果在InstantRun模式下运行,必须开启调试模式!线上版本需要关闭,否则有安全风险)}ARouter.init(mApplication); // 尽可能早,推荐在Application中初始化
step.2
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()); }}
step.3
声明拦截器,拦截器会在跳转之间执行,多个拦截器会按优先级顺序依次执行,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("拦截器被初始化"); }}
step.4
通过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>
step.5
传递自定义对象点我
step.6
处理跳转结果
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(); } });
step.7
降级策略点我
step.8
为目标页面声明更多信息
// 我们经常需要在目标页面中配置一些属性,比方说"是否需要登陆"之类的// 可以通过 Route 注解中的 extras 属性进行扩展,这个属性是一个 int值,换句话说,单个int有4字节,也就是32位,可以配置32个开关// 剩下的可以自行发挥,通过字节操作可以标识32个开关,通过开关标记目标页面的一些属性,在拦截器中可以拿到这个标记进行业务逻辑判断@Route(path = "/login/activity_3", extras = -100)
拦截器判断
if (postcard.getExtra()==-100){ callback.onInterrupt(new RuntimeException("我看你不顺眼")); }
step.9
9.1 通过依赖注入解耦:服务管理-暴露服务
9.2 通过依赖注入解耦:服务管理-发现服务
详情点我
step.10
更多功能
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,第二个参数则是RequestCodeARouter.getInstance().build("/home/main", "ap").navigation(this, 5);// 直接传递BundleBundle params = new Bundle();ARouter.getInstance() .build("/home/main") .with(params) .navigation();// 指定FlagARouter.getInstance() .build("/home/main") .withFlags(); .navigation();// 获取FragmentFragment 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方法中传入当前ActivityARouter.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
更多相关文章
- 解决Android编译时无法匹配到AVD的问题
- android之android.intent.category.DEFAULT的用途和使用 隐式Int
- Android(安卓)- Linkify 详解
- menu.addIntentOptions 添加动态菜单详解
- intent-filter的data属性详述
- Android(安卓)Activity之间跳转总结
- 待研究
- Android学习(八)AutoCompleteTextView控件
- Android(安卓)混合模式之 PorterDuffXfermode