在组件化设计中,除了宿主app能够集成其他组件之外,其他模块之间其实是没有依赖的,相互独立的,例如video和mine之前,video想要调用mine中的图片,只能通过路由完成
组件数据共享
1 组件间图片共享
首先,在compiler_api中,定义图片共享的标准Call,与IARouterPath Group同级,在公共基础库中,定义某个模块,例如register模块的标准
interface Call {
}
/**
* 定义register模块 图片的标准
*/
interface RegisterDrawable : Call {
fun getDrawable():Int
}
在register模块中,真正实现这个类
@LayRouter(group = "register",path = "register/getDrawable")
class RegisterDrawableImpl : RegisterDrawable {
override fun getDrawable(): Int {
return R.drawable.ic_baseline_6k_plus_24
}
}
1.1 AnnatationProcessor注解处理
这里要注意的是,在RegisterDrawableImpl上使用了LayRouter注解,这个注解在编译的时候,会被扫描到,如果按照之前注解处理器的标准,会报错
Caused by: java.lang.Exception: @LayRouter注解只能在Activity或者Fragment上使用
at com.study.lay_compiler.AnnotationProcessor.process(AnnotationProcessor.kt:107)
这里处理一下,做一个判断,新加了一个Call类型
val callMirror = elementTool!!.getTypeElement(CALL_PACKAGE).asType()
else if(typeTool!!.isSubtype(element.asType(),callMirror)){
routeBean.setType(RouterType.CALL)
}
public class ARouter_Path_register : IARoutPath {
public override fun getARoutePath(): Map<String, RouteBean> {
val pathMap = mutableMapOf<String,RouteBean>()
pathMap.put("register/getDrawable",RouteBean.create(RegisterDrawableImpl::class,RouterType.CALL,"register/getDrawable","register"))
pathMap.put("register/RegisterActivity",RouteBean.create(RegisterActivity::class,RouterType.ACTIVITY,"register/RegisterActivity","register"))
return pathMap
}
}
最终生成的路由代码中,我们需要的其实就是RouteBean中的RegisterDrawableImpl来传递参数
1.2 RouterManager修改
如果是CALL类型,则直接返回实现类
if(routeBean.getType() == RouterType.ACTIVITY){
//如果是Activity,那么就执行跳转的逻辑
val intent = Intent().apply {
setClass(context,routeBean.getModel().java)
putExtras(manager.getBundle())
}
context.startActivity(intent,manager.getBundle())
}else if(routeBean.getType() == RouterType.CALL){
//如果是CALL类型,需要执行图片懒加载,返回的就是实现类
return routeBean.getModel().java.newInstance()
}
1.3 ParamterProcessor修改
else if(typeUtils.isSubtype(typeMirror, callMirror)){
//activityInstance.drawable = RouterManager.instance.build("").navigation(this) as xxx
//如果是图片类型,需要动态加载
func.addStatement(
"%N.%L = %T.instance.build(%S)!!.navigation(activity) as %T",
property,
element.simpleName.toString(),
ClassName("com.study.complier_api2","RouterManager"),
name,
//难点,如何获取属性的类型
element.asType().asTypeName()
)
}
通过RouterManager加载目标路由地址的资源文件,然后给调用方赋值
public class MainActivityParams : ParameterGet {
public override fun getParameter(activity: Any): Unit {
val activityInstance = activity as MainActivity
activityInstance.drawable =
RouterManager.instance.build("register/getDrawable")!!.navigation(activity) as
RegisterDrawable
}
}
最终生成的参数代码,其中在MainActivity中调用register模块的资源文件
@Parameter(name="register/getDrawable")
lateinit var drawable:RegisterDrawable
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
ParameterManager.instance.loadParams(this)!!.getParameter(this)
val drawable1 = drawable.getDrawable()
findViewById<ImageView>(R.id.iv_register).setImageResource(drawable1)
在MainActivity中,调用ParameterManager获取参数,就将register模块中的资源通过懒加载的方式赋值给drawable
2 组件间Bean共享
和图片一样,Bean也是一种资源,只需要定义每个模块对于bean的标准,那么就可以在组件之间实现共享
1 公共基础库中,定义某个模块对于bean的标准
/**
* 定义Register模块对于bean的标准
*/
interface RegisterUser : Call {
//获取具体的bean
fun getUserInfo():BaseUser
}
2 在具体模块中具体实现这个标准,使用路由实现
@LayRouter(group = "register",path = "register/getUserInfo")
class RegisterUserImpl : RegisterUser {
override fun getUserInfo(): BaseUser {
val info = RegisterUserInfo()
info.name = "Mike"
info.age = 23
info.token = "sfjal;fnalnfa;fafam;"
return info
}
}
最终生成的path代码就是这样的
public class ARouter_Path_register : IARoutPath {
public override fun getARoutePath(): Map<String, RouteBean> {
val pathMap = mutableMapOf<String,RouteBean>()
pathMap.put("register/getDrawable",RouteBean.create(RegisterDrawableImpl::class,RouterType.CALL,"register/getDrawable","register"))
pathMap.put("register/RegisterActivity",RouteBean.create(RegisterActivity::class,RouterType.ACTIVITY,"register/RegisterActivity","register"))
pathMap.put("register/getUserInfo",RouteBean.create(RegisterUserImpl::class,RouterType.CALL,"register/getUserInfo","register"))
return pathMap
}
}
使用方式和图片一致,只要是一个标准即可
@Parameter(name="register/getDrawable")
lateinit var drawable:RegisterDrawable
@Parameter(name = "register/getUserInfo")
lateinit var bean:RegisterUser
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
ParameterManager.instance.loadParams(this)!!.getParameter(this)
findViewById<TextView>(R.id.tv_hello).text = bean.getUserInfo().name
对于组件之间的数据共享,其实就是通过基础库做每个模块的资源标准定义,然后每个模块做标准的具体实现,通过路由 + Paramter的方式实现数据的懒加载