随着app项目的逐步迭代开发,单独运行调试比较耗时,实行项目组件化拆分迫在眉睫,而跨组件通信是必须要解决的问题,而ARouter算是一个比较成熟的路由解决方案,所以写下此篇文章,借此来记录。
apply plugin: 'kotlin-kapt'
android {
kapt {
arguments {
arg("AROUTER_MODULE_NAME", project.getName())
}
}
}
dependencies {
implementation 'com.alibaba:arouter-api:1.5.0'
kapt 'com.alibaba:arouter-compiler:1.2.2'
}
if (BuildConfig.DEBUG) {
// 这两行必须写在init之前,否则这些配置在init过程中将无效
ARouter.openLog(); // 打印日志
ARouter.openDebug();
// 开启调试模式(如果在InstantRun模式下运行,必须开启调试模式!线上版本需要关闭,否则有安全风险)
}
ARouter.init(this);
object PathConstant{
const val SERVICE_PATH="/app/service_path"
const val SECOND_ACTIVITY_PATH="/app/RouterSecondActivity"
const val INNER_FRAGMENT_PATH="/app/InnerFragment"
// secondModule
const val SECOND_MODULE_ACTIVITY_PATH="/secondmodule/MainActivity"
}
object ExtraKeyConstant {
const val KEY_STRING_EXTRA="key_string_extra"
const val KEY_INT_EXTRA="key_int_extra"
const val KEY_BOOLEAN_EXTRA="key_boolean_extra"
const val KEY_LONG_EXTRA="key_long_extra"
const val KEY_OBJECT_EXTRA="key_object_extra"
}
// 带基本类型参数
btn_skip_two.setOnClickListener {
ARouter.getInstance().build(PathConstant.APP_MODULE_ROUTER_SECOND_ACTIVITY)
.withString(ExtraKeyConstant.KEY_STRING_EXTRA, "ARouter")
.withInt(ExtraKeyConstant.KEY_INT_EXTRA, 10)
.withLong(ExtraKeyConstant.KEY_LONG_EXTRA, 1)
.withBoolean(ExtraKeyConstant.KEY_BOOLEAN_EXTRA, true)
.navigation()
}
// 传递序列化对象
btn_skip_with_obj.setOnClickListener {
ARouter.getInstance().build(PathConstant.APP_MODULE_ROUTER_SECOND_ACTIVITY)
.withSerializable(ExtraKeyConstant.KEY_OBJECT_EXTRA, PersonEntity("peter", 18))
.navigation()
}
// 传递object
btn_skip_with_list.setOnClickListener {
val list = ArrayList()
list.add(PersonEntity("peter", 18))
list.add(PersonEntity("tommy", 20))
ARouter.getInstance().build(PathConstant.APP_MODULE_ROUTER_SECOND_ACTIVITY)
.withObject(ExtraKeyConstant.KEY_OBJECT_EXTRA, list)
.navigation()
}
// 跨module跳转
btn_jump_second_module.setOnClickListener {
ARouter.getInstance().build(PathConstant.SECOND_MODULE_ACTIVITY_PATH)
.withTransition(R.anim.slide_in_bottom, R.anim.slide_out_bottom)
.withString(ExtraKeyConstant.KEY_STRING_EXTRA, "helloWorld").navigation()
}
注意跨module跳转一定要在主module中添加其他module的引用,否则会找不到path
implementation project(':baselibrary')
implementation project(':secondmodule')
通过withObject()传递object,一定要新建一个类),然后实现 SerializationService,并使用@Route注解标注(方便用户自行选择序列化方式),否则会报空指针异常
implementation 'com.google.code.gson:gson:2.8.6'
@Route(path = "/service/json")
class JsonServiceImpl : SerializationService {
private var mGson: Gson? = null
override fun init(context: Context?) {
mGson = Gson()
}
override fun json2Object(text: String?, clazz: Class?): T {
checkJson()
return mGson!!.fromJson(text, clazz)
}
override fun object2Json(instance: Any?): String {
checkJson()
return mGson!!.toJson(instance)
}
override fun parseObject(input: String?, clazz: Type?): T {
checkJson()
return mGson!!.fromJson(input, clazz)
}
fun checkJson() {
if (mGson == null) {
mGson = Gson()
}
}
}
@Route(path = PathConstant.APP_MODULE_ROUTER_SECOND_ACTIVITY)
class RouterSecondActivity : AppCompatActivity() {
@Autowired(name = ExtraKeyConstant.KEY_STRING_EXTRA)
@JvmField
var text = ""
@Autowired(name = ExtraKeyConstant.KEY_INT_EXTRA)
@JvmField
var intParam =0
@Autowired(name = ExtraKeyConstant.KEY_BOOLEAN_EXTRA)
@JvmField
var booleanParam =false
@Autowired(name = ExtraKeyConstant.KEY_LONG_EXTRA)
@JvmField
var longParam =0
@Autowired(name = ExtraKeyConstant.KEY_SERIALIZABLE_EXTRA)
@JvmField
var mPerson: PersonEntity? = null
@Autowired(name = ExtraKeyConstant.KEY_OBJECT_EXTRA)
@JvmField
var mList: List? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// 注意一定要注入才能接收到参数
ARouter.getInstance().inject(this)
setContentView(R.layout.activity_router_second)
initData()
}
private fun initData() {
btn_second_text.text = "String data is $text int data is $intParam long data is $longParam boolean data is $booleanParam "
// 接收object参数
btn_second_obj_text.text = mPerson?.name + mPerson?.age
// 接收list
btn_second_list_text.text=if (mList.isNullOrEmpty()) "emptyList" else "list size is ${mList?.size}"
}
}
起始页
// 类似startActivityForResult
btn_skip_with_response.setOnClickListener {
ARouter.getInstance().build(PathConstant.APP_MODULE_ROUTER_SECOND_ACTIVITY).navigation(this,
REQUEST_CODE)
}
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (requestCode== REQUEST_CODE&&resultCode== RESULT_CODE){
Log.d(TAG,data?.getStringExtra(ExtraKeyConstant.KEY_SECOND_ACTIVITY_EXTRA))
}
}
companion object{
const val REQUEST_CODE=0X01
const val RESULT_CODE=0X02
}
结果页
/**
* 设置返回数据
*/
private fun setResultData() {
val intent = Intent()
intent.putExtra(ExtraKeyConstant.KEY_SECOND_ACTIVITY_EXTRA, "secondActivityData")
setResult(RouterMainActivity.RESULT_CODE, intent)
}
// 获取跳转过程监听
btn_skip_with_result.setOnClickListener {
val list = ArrayList()
list.add(PersonEntity("peter", 18))
list.add(PersonEntity("tommy", 20))
ARouter.getInstance().build(PathConstant.APP_MODULE_ROUTER_SECOND_ACTIVITY)
.withObject(ExtraKeyConstant.KEY_OBJECT_EXTRA, list)
.navigation(this, object : NavigationCallback {
override fun onLost(postcard: Postcard?) {
Log.d(TAG,"onLost")
}
override fun onFound(postcard: Postcard?) {
Log.d(TAG,"onFound")
}
override fun onInterrupt(postcard: Postcard?) {
Log.d(TAG,"onInterrupt")
}
override fun onArrival(postcard: Postcard?) {
Log.d(TAG,"onArrival")
}
})
}
AOP面向切面编程,做自己想做的事情
@Interceptor(priority = 8, name = "测试用拦截器")
class RouterInterceptor : IInterceptor {
override fun process(postcard: Postcard?, callback: InterceptorCallback?) {
Log.d("peter","埋点")
callback?.onContinue(postcard)
Log.d("peter","process")
}
override fun init(context: Context?) {
Log.d("peter","init")
}
}
@Route(path = PathConstant.INNER_FRAGMENT_PATH)
class InnerFragment : Fragment() {
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
return LayoutInflater.from(context).inflate(R.layout.fragment_inner, container,false)
}
}
// 获取fragment实例
val fragment = ARouter.getInstance().build(PathConstant.INNER_FRAGMENT_PATH).navigation() as Fragment
Log.d("peter", fragment.javaClass.canonicalName)
类似接口回调实现
interface IService : IProvider {
override fun init(context: Context?) {
}
fun transferWords(words: String):String
}
@Route(path = PathConstant.SERVICE_PATH)
class ServiceImpl :IService{
override fun transferWords(words: String): String {
Log.d("peter",words)
return "words is helloWorld"
}
}
btn_jump_service.setOnClickListener {
val serviceImpl= ARouter.getInstance().build(PathConstant.SERVICE_PATH).navigation() as IService
serviceImpl.transferWords("你好")
}
btn_jump_with_anim.setOnClickListener {
ARouter.getInstance().build(PathConstant.SECOND_ACTIVITY_PATH)
.withTransition(R.anim.slide_in_bottom, R.anim.slide_out_bottom)
.withString(ExtraKeyConstant.KEY_STRING_EXTRA, "helloWorld").navigation()
}
slide_in_bottom
slide_out_bottom
-keep public class com.alibaba.android.arouter.routes.**{*;}
-keep public class com.alibaba.android.arouter.facade.**{*;}
-keep class * implements com.alibaba.android.arouter.facade.template.ISyringe{*;}
# 如果使用了 byType 的方式获取 Service,需添加下面规则,保护接口
-keep interface * implements com.alibaba.android.arouter.facade.template.IProvider
# 如果使用了 单类注入,即不定义接口实现 IProvider,需添加下面规则,保护实现
# -keep class * implements com.alibaba.android.arouter.facade.template.IProvider
ARouter中文文档README_CN