GitHub
https://github.com/alibaba/ARouter
匯入
- 添加依賴
id 'kotlin-kapt'
android {
defaultConfig {
...
kapt {
arguments {
//根據模塊名來命名路由根節點
arg("AROUTER_MODULE_NAME", project.getName())
//生成Json檔案
arg("AROUTER_GENERATE_DOC", "enable")
}
}
}
}
dependencies {
...
//ARouter的api
implementation 'com.alibaba:arouter-api:1.5.1'
//kotlin中使用kapt,ARouter的注解處理器
kapt 'com.alibaba:arouter-compiler:1.2.2'
}
- 其他用到ARouter注解的模塊中,也需要加入
//kotlin中使用kapt,ARouter的注解處理器
kapt 'com.alibaba:arouter-compiler:1.2.2'
- (可選)在專案的根build.gradle中,推薦匯入該插件,可以在編譯階段完成初始化時的事情,可以加快app的啟動
dependencies {
...
classpath "com.alibaba:arouter-register:1.0.2"
}
Base模塊下增加介面IIProvider
package com.zhangyu.router
import com.alibaba.android.arouter.facade.template.IProvider
interface IIProvider : IProvider {
fun startLoginActivity(from: String)
fun startMainActivity(from: String)
fun startSearchActivity(from: String)
fun startEditorActivity(from: String)
}
object RouteFlag {
//為什么可以使用route注解的extra引數為目標頁指定屬性
//因為Int數值在記憶體中占4個位元組,每個位元組占8位,所以利用extras欄位我們可以為目標頁指定32個開關
const val FLAG_LOGIN: Int = 0x01
const val FLAG_AUTHORITY = FLAG_LOGIN.shl(1)//等同于java中的FLAG_LOGIN<<1
const val FLAG_VIP = FLAG_AUTHORITY.shl(1)
}
app模塊中實作IIProvider 介面
@Route(path = JumpProvider.PATH)
class JumpProvider : IIProvider {
companion object {
const val PATH = "/service/provider"
}
override fun init(context: Context?) {
}
override fun startLoginActivity(from: String) {
ARouter.getInstance().build(LoginActivity.PATH)
.navigation()
}
override fun startMainActivity(from: String) {
ARouter.getInstance().build(MainActivity.PATH)
.navigation()
}
override fun startSearchActivity(from: String) {
ARouter.getInstance().build(SearchActivity.PATH)
.navigation()
}
override fun startEditorActivity(from: String) {
ARouter.getInstance().build(EditActivity.PATH)
.navigation()
}
}
定義幾個頁面
- MainActivity
private const val TAG = "MainActivity"
@Route(path = MainActivity.PATH)
class MainActivity : AppCompatActivity() {
companion object {
const val PATH = "/app/main"
}
private lateinit var binding: ActivityMainBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = DataBindingUtil.setContentView(this, R.layout.activity_main)
binding.btGotoLogin.setOnClickListener {
JumpProvider().startLoginActivity("MainActivity")
}
binding.btGotoEditor.setOnClickListener {
JumpProvider().startEditorActivity("MainActivity")
}
binding.btGotoSearch.setOnClickListener {
JumpProvider().startSearchActivity("MainActivity")
}
binding.btGotoError.setOnClickListener {
//傳入一個錯誤的路徑
ARouter.getInstance()
.build("/path/unknown")
.navigation()
}
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
Log.d(TAG, "onActivityResult: ${data?.getStringExtra("key")}")
}
}
- LoginActivity
@Route(path = LoginActivity.PATH)
class LoginActivity : AppCompatActivity() {
companion object {
const val PATH = "/app/login"
}
@JvmField
@Autowired
var from = ""
lateinit var binding: ActivityLoginBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = DataBindingUtil.setContentView(this, R.layout.activity_login)
binding.lifecycleOwner = this
//設定引數的自動注入
ARouter.getInstance().inject(this)
//列印
Log.d(TAG, "onCreate: from=$from")
initView()
}
private fun initView() {
binding.btLogin.setOnClickListener {
LoginRepositoryProvider.getInstance().login()
finish()
}
binding.btLogout.setOnClickListener {
LoginRepositoryProvider.getInstance().logout()
finish()
}
}
}
private const val TAG = "LoginActivity"
- EditActivity(低層模塊,Editor模塊中)
- 傳入extras = RouteFlag.FLAG_LOGIN用于登錄攔截,進入該頁面需要先登錄
- private val jumpProvider by lazy { ARouter.getInstance().navigation(IIProvider::class.java) }子模塊下獲取IIProvider的實體 jumpProvider
@Route(path = EditActivity.PATH, extras = RouteFlag.FLAG_LOGIN)
class EditActivity : AppCompatActivity() {
companion object {
const val PATH = "/editor/edit"
}
private lateinit var binding: ActivityEditorBinding
private val jumpProvider by lazy { ARouter.getInstance().navigation(IIProvider::class.java) }
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = DataBindingUtil.setContentView(this, R.layout.activity_editor)
binding.btGotoSearch.setOnClickListener {
jumpProvider.startSearchActivity("EditorActivity")
}
}
}
定義一個攔截器(例如登錄攔截)
//定義一個攔截器,需要name隨便寫一個即可
@Interceptor(name = "/service/interceptor", priority = 9)
class GlobalInterceptor : IInterceptor {
private var context: Context? = null
override fun init(context: Context?) {
this.context = context
}
override fun process(postcard: Postcard?, callback: InterceptorCallback?) {
val flag = postcard?.extra
if (flag?.and(RouteFlag.FLAG_LOGIN) != 0) {
//判斷是否已經登錄
val isLogin = LoginRepositoryProvider.getInstance().isLogin()
if (!isLogin) {
ARouter.getInstance().build(LoginActivity.PATH)
.navigation()
showToast("需要登錄")
} else {
//已經登錄不需要攔截
callback?.onContinue(postcard)
}
} else {
//不需要攔截
callback?.onContinue(postcard)
}
}
private fun showToast(msg: String) {
//攔截器在子執行緒中,需要切換到主執行緒更新UI
Handler(Looper.getMainLooper()).post {
Toast.makeText(context, msg, Toast.LENGTH_SHORT).show()
}
}
}
定義一個全域的降級服務(重定向)
//全域降級服務,當路由的時候,目標不存在,重定向到統一錯誤頁面
//定義一個任意的path注解即可生效
@Route(path = "/service/degrade")
class DegradeServiceImp : DegradeService {
override fun init(context: Context?) {
}
//頁面沒有找到時觸發
override fun onLost(context: Context?, postcard: Postcard?) {
ARouter.getInstance().build(ErrorActivity.PATH)
.greenChannel()//greenChannel不會被攔截器攔截
.navigation()
}
}
生成的檔案的目錄

使用中的問題
- const val PATH = “/app/main”
const val PATH = “/editor/edit”
不同模塊下的頁面要分配在不同的group中,例如app下的MainActivity定義group為app,editor模塊下的EditActivity定義group為editor
參考資料
- 談談App的統一跳轉和ARouter
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/259266.html
標籤:其他
