赞
踩
随着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<PersonEntity>() 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 <T> json2Object(text: String?, clazz: Class<T>?): T { checkJson() return mGson!!.fromJson(text, clazz) } override fun object2Json(instance: Any?): String { checkJson() return mGson!!.toJson(instance) } override fun <T> 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<PersonEntity>? = 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<PersonEntity>() 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
<?xml version="1.0" encoding="utf-8"?>
<translate xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="300"
android:fromYDelta="0%"
android:interpolator="@android:anim/accelerate_decelerate_interpolator"
android:toYDelta="100%"/>
slide_out_bottom
<?xml version="1.0" encoding="utf-8"?>
<translate xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="300"
android:fromYDelta="100%"
android:interpolator="@android:anim/accelerate_decelerate_interpolator"
android:toYDelta="0%"/>
-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
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。