Android組件化工具ARouter使用方法詳細分析

前言

組件,就是對數據和方法的簡單封裝,功能單一,高類聚,是業務劃分的最小粒度。組件化是基於可重用的目的,將大型軟件系統按照分離關註點的形式,拆分成多個獨立組件,使得整個軟件是單個或多個組件元件組裝起來。那組件之間如何通信呢?這就得益於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 的路由信息註冊

到此這篇關於Android組件化工具ARouter使用方法詳細分析的文章就介紹到這瞭,更多相關Android ARouter內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!

推薦閱讀: