網站首頁 編程語言 正文
前言
組件,就是對數據和方法的簡單封裝,功能單一,高類聚,是業務劃分的最小粒度。組件化是基于可重用的目的,將大型軟件系統按照分離關注點的形式,拆分成多個獨立組件,使得整個軟件是單個或多個組件元件組裝起來。那組件之間如何通信呢?這就得益于ARouter。
Android原生的路由方案是Intent的顯式和隱式跳轉,顯式需要對目標的引用,會導致不同頁面的耦合,隱式集中配置在manifest中,不利于維護和管理。況且,在組件化開發中,各模塊之間無法直接引用,那么,ARouter路由框架就派上用場了。
一個用于幫助 Android App 進行組件化改造的框架 —— 支持模塊間的路由、通信、解耦
原理簡述
ARouter通過APT技術,生成保存路徑(路由path)和被注解(@Router)的組件類的映射關系的類,利用這些保存了映射關系的類,根據用戶的請求postcard尋找到要跳轉的目標地址,使用Intent跳轉。所以,該框架的核心是利用APT生成的映射關系,APT的作用是在編譯階段掃描并處理代碼中的注解,然后根據注解輸出Java文件。
基本使用
添加依賴和配置,注意,每個使用到ARouter的Module都要引入
plugins {
? ? id 'com.android.library'
? ? id 'org.jetbrains.kotlin.android'
? ? id 'kotlin-kapt'
}
? ? kapt {
? ? ? ? arguments {
? ? ? ? ? ? arg("AROUTER_MODULE_NAME", project.getName())
? ? ? ? }
? ? }
? ? implementation 'com.alibaba:arouter-api:1.5.2'
? ? kapt 'com.alibaba:arouter-compiler:1.5.2'
引入后需要注意的一點是:要在gradle.properties文件中加入下面這個,不然會編譯不過去,這也是我遇到的一個小坑。
android.enableJetifier=true
在Application中初始化
if (isDebug()) {
ARouter.openLog() //打印日志
ARouter.openDebug() //開啟調試模式,線上需關閉
}
ARouter.init(this)
在支持路由的頁面上添加如下的注解,路徑至少需要兩級
@Route(path = "/home/HomeActivity")
class HomeActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_home)
}
}
然后在另一個Activity中,進行跳轉
ARouter.getInstance().build("/home/HomeActivity").navigation()
如果需要傳遞參數的話,可以這樣做
ARouter.getInstance().build("/home/HomeActivity")
.withString("name", "Uncle Xing")
.withInt("age", 25)
.withSerializable("user", User("Uncle Xing", 25))
.navigation()
然后在目標Activity中通過Autowired接收,ARouter會自動對字段進行賦值,無需主動獲取
@Route(path = "/home/HomeActivity")
class HomeActivity : AppCompatActivity() {
@JvmField
@Autowired
var name = ""
@JvmField
@Autowired
var age = 0
@JvmField
@Autowired
var user: User? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_home)
initView()
}
private fun initView() {
ARouter.getInstance().inject(this)
findViewById<TextView>(R.id.name).text = name
findViewById<TextView>(R.id.age).text = age.toString()
findViewById<TextView>(R.id.user).text = user.toString()
}
}
在組件化開發中,我們通常會有一些公共Module來作為共有功能,那這個時候就可以使用ARouter的依賴注入解耦,組件件的通信,首先我們要聲明接口,其他組件通過這個接口來調用方法
interface MyProvider : IProvider {
fun getData(): String
}
實現類
@Route(path = "/common/MyProviderImpl")
class MyProviderImpl : MyProvider {
override fun getData(): String {
return "Welcome to my blog"
}
override fun init(context: Context?) {
}
}
其他組件的Activity就可以這樣調用
class MainActivity : AppCompatActivity() {
/**
* 當一個接口只有一個實現類的時候,Autowired可以不設置name
*/
@JvmField
@Autowired(name = "/common/MyProviderImpl")
var myProvider: MyProvider? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
initView()
}
private fun initView() {
ARouter.getInstance().inject(this)
findViewById<TextView>(R.id.provider_text).text = myProvider?.getData()
}
}
上面是使用依賴注入的方式,通過注解標注字段,即可使用,無需主動獲取,除此之外,我們也可以使用賴查找的方式,比如上面的代碼我們也可以寫成這樣
class MainActivity : AppCompatActivity() {
var myProvider: MyProvider? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
initView()
}
private fun initView() {
// ARouter.getInstance().inject(this) 這種方式不需要這句
myProvider =
ARouter.getInstance().build("/common/MyProviderImpl").navigation() as MyProvider
/**
* 發現的方式有byName和byType,如果一個接口只有一個實現的話,也可以使用byType,可以寫成
* myProvider = ARouter.getInstance().navigation(MyProvider::class.java)
*/
findViewById<TextView>(R.id.provider_text).text = myProvider?.getData()
}
}
我們也可以動態注冊路由,這樣,目標頁面和服務就可以不標注 @Route 注解。不過,一般組件化項目都不會這樣干,適合部分插件化架構的項目或其他場景。
ARouter.getInstance().addRouteGroup {
it["/home/HomeActivity"] = RouteMeta.build(
RouteType.ACTIVITY, //路由信息
HomeActivity::class.java, //目標class
"/home/HomeActivity", //path
"home", //Group,盡量保持和path的第一段相同
0, 0
)
}
注意:同一批次僅允許相同 group 的路由信息注冊
原文鏈接:https://blog.csdn.net/qq_45485851/article/details/126282874
相關推薦
- 2023-01-10 Flutter?RendererBinding作用源碼分析_IOS
- 2022-07-02 ansible模塊之include_tasks:為什么加了tags后導入的任務沒有執行?
- 2022-11-04 react-router-dom?v6?使用詳細示例_React
- 2022-11-07 Python實現四舍五入的兩個方法總結_python
- 2022-03-26 C++?Primer學習記錄之變量_C 語言
- 2022-04-09 C++實現簡單的計算器功能_C 語言
- 2022-10-26 C#實現接收QQ郵件的示例代碼_C#教程
- 2022-06-08 Python?全局空間和局部空間_python
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支