这几天做项目调整,将现有的Android项目中所有的页面跳转进行整体迁移到ARouter,现将项目迁移过程中所遇到的问题记录一下。目前网上很多关于ARouter的文章都是转载的,导致在解决问题的过程中一查资料同质化的文章太严重了,不得不吐槽一下,当然也有很多优秀的文章。不可否认ARouter是一个很优秀的路由组件,能够很方便的实现Activity解藕,给模块化扫清了很大的障碍。言归正传具体记录所遇到的问题
-
Instant Run
Android Studio 开启了Instant Run 后在ARouter.getInstance().init(app)之前一定要记得开启debug模式 ARouter.openDebug(),为什么要这么做是因为第一次运行的时候ARouter会将所有的路由扫描并保存到SharePreference中,后续都是从SP中直接拿路由去映射Activity如果,没有开启了Instant Run 后续的代码会增量编译,但是这时候并不会重新去扫描路由这样就会导致新的路由没有更新到SP中,后面在做跳转的时候会找不到路由 -
路由
ARouter 官方建议我们最少使用两层路由,第一层是作为分组名(默认实现)也可以通过group进行定义分组,我们在定义路由的时候一定要注意Activity 之间跳转的路由要以 "/"开头,否则在跳转的时候会提示找不到路由,切记!!! 血的教训。 -
拦截器
ARouter支持拦截器,让我们在页面跳转的时候可以做一些通用的拦截操作。我们可以在拦截器的process方法中处理拦截的逻辑但是有两个方法onContinue()和onIntercept 我们必须要调用一个,否则路由就无法正常跳转 -
对象传值
ARouter简化了页面跳转时的参数传递,对于基础数据类型的传递一般不会出什么问题,但是在传递对象的时候需要注意,我们先说一下ARouter是如何传递对象的,在调用withObject方法时,会调用我们自己实现的SerializationService将对象转换成JSON字符串然后将字符串保存到Intent中,然后在目标Activity中通过Autowired注解标记要接收传值的属性,并通过SerializationService将Json字符串反序列化成对象,这就是我们为什么要实现一个全局的SerializationService。但是了在这套实现逻辑中我认为存在一个bug,首先我们在调用withObject方法的时候根本没有关心传递的对象有没有实现Serializable接口,但是在目标Activity中取值的时候却做了判断,如果是实现了Serializable接口则取值的时候直接通过getSerializableExtra来获取Intent中的值,如果没有实现Serializable,则先将json字符串取出然后通过serializationService.parseObject来反序列化成对象,这样就出问题了,如果我传递的对象实现了Serializable接口那么在调用withObject方法的时候已经把对象序列化成JSON字符串了,那么我在取值的时候还通过getSerializableExtra来取值拿到的是一个字符串,但是我们想要的是一个对象,这里就会报类型转化异常,由于内部进行来异常捕获,返回的就是一个null值,这也是为什么在配置都对的前提下调用withObject方法后取值依然是null,要解决这个问题只需要把传递对象的Serializable去掉即可正确。所以要想完成正确的通过注解获取传递的对象需要注意下面几步:
1.先要自己实现一个SerializationService 就是一个全局的序列化服务,这个服务可以根据自己业务的需要选择Gson或者fastjon亦或JSONObject。
2.给我们自己实现的SerializationService添加路由。
3.定义需要传输的对象
4.在目标Activity进行参数的接收,敲黑板划重点,我们在传递对象的时候会调用withObject("obj",Object) 方法,这里的key 也就是obj必须和目标Activity中定义的接收属性是一致,如果不一致可以通过Autowired注解的name属性来设置 例如
@Autowired
Object obj;
或
@Autowired(name="obj")
Object objA;
- 在目标Activity定义的属性obj 不能通过private修饰,否则编译的时候会报错,而且还不知道哪里有错,通过注解主要是为了减少代码量而采用直接赋值的方式,如果用private修饰则需要通过反射机制去赋值,这样在性能和代码上都得不偿失。惊不惊喜,意不意外。
网友评论