基于Arouter實(shí)現(xiàn)的組件化方案說(shuō)明

image.png

基于Arouter實(shí)現(xiàn)的組件化方案說(shuō)明:

基于Arouter實(shí)現(xiàn)的組件化方案說(shuō)明:

一個(gè)項(xiàng)目欺殿,隨著業(yè)務(wù)的發(fā)展,模塊會(huì)變的越來(lái)越多饶囚,代碼量也會(huì)變的異常龐大军援,進(jìn)而可能開(kāi)發(fā)的人會(huì)越來(lái)越多,這種情況下如果還是基于單一工程架構(gòu)屏箍,那就需要每一個(gè)開(kāi)發(fā)者都熟悉所有的代碼绘梦,而且代碼之間耦合嚴(yán)重,一個(gè)模塊穿插著大量其他業(yè)務(wù)模塊的邏輯赴魁,嚴(yán)重的話(huà)可能使項(xiàng)目處于牽一發(fā)而動(dòng)全身卸奉,不想輕易修改的局面;而且龐大的單一工程項(xiàng)目會(huì)導(dǎo)致編譯速度極慢颖御,開(kāi)發(fā)者長(zhǎng)時(shí)間等待編譯結(jié)果榄棵,非常不利于開(kāi)發(fā)工作。所以潘拱,就需要一個(gè)靈活的架構(gòu)來(lái)解決這些問(wèn)題疹鳄,組件化架構(gòu)思想應(yīng)運(yùn)而生。

整體結(jié)構(gòu)

  • common:基礎(chǔ)組件部分芦岂,與業(yè)務(wù)無(wú)關(guān)尚辑,需要所有組件共同依賴(lài)的部分,如:網(wǎng)絡(luò)請(qǐng)求封裝盔腔、圖片加載封裝杠茬、ui相關(guān)基類(lèi)、工具集合等(當(dāng)然這些內(nèi)容可以依據(jù)分層原則放在不同的基礎(chǔ)module中)
  • router-comp:路由驅(qū)動(dòng)組件弛随,承載整個(gè)項(xiàng)目的路由工作
  • comp1:業(yè)務(wù)組件1瓢喉,如視頻組件,可獨(dú)立運(yùn)行
  • comp2:業(yè)務(wù)組件2舀透,如新聞組件栓票,可獨(dú)立運(yùn)行
  • comp3:業(yè)務(wù)組件3,如視頻組件愕够,可獨(dú)立運(yùn)行
  • app:殼工程走贪,用于將各個(gè)組件組裝成一個(gè)完成app

組件化所面臨的問(wèn)題:

  • 集成模式與組件模式轉(zhuǎn)換(熱插拔)
  • 組件之間頁(yè)面跳轉(zhuǎn)(路由)
  • 組件之間通信、調(diào)用彼此服務(wù)
  • 打包混淆

組件化的實(shí)現(xiàn)

針對(duì)上面所說(shuō)的幾個(gè)問(wèn)題惑芭,下面我們逐個(gè)說(shuō)明它們的解決方案坠狡,當(dāng)解決完這些問(wèn)題,你會(huì)發(fā)現(xiàn)遂跟,你已經(jīng)搭建了一個(gè)基于組件化的項(xiàng)目逃沿。下圖是一個(gè)完整的組件化項(xiàng)目結(jié)構(gòu):common是基礎(chǔ)組件module婴渡,作為library存在,需要所有組件依賴(lài)凯亮;comp1边臼、comp2作為組件存在,可配置成library或可獨(dú)立運(yùn)行的module假消;app是個(gè)殼柠并,通過(guò)組裝組件實(shí)現(xiàn)其價(jià)值。

在這里插入圖片描述

集成模式與組件模式轉(zhuǎn)換(熱插拔)

Android工程通過(guò)gradle構(gòu)建富拗,通過(guò)配置每個(gè)module的gradle臼予,來(lái)實(shí)現(xiàn)module的不同表現(xiàn)。Android Studio的module有兩種屬性媒峡,分別是:

  • application屬性:可獨(dú)立運(yùn)行,也就是我們的app
  • library屬性:不可獨(dú)立運(yùn)行葵擎,被app依賴(lài)的庫(kù)

module屬性通過(guò)其目錄下的gradle文件配置谅阿,當(dāng)module屬性為application時(shí),該module作為完整的app存在酬滤,可以獨(dú)自運(yùn)行签餐,方便編譯和調(diào)試;當(dāng)module屬性為library時(shí)盯串,該module作為一個(gè)依賴(lài)庫(kù)氯檐,被殼工程依賴(lài)并組裝成一個(gè)app。那么如何讓這兩種模式可以自動(dòng)轉(zhuǎn)換呢体捏?如果每次切換模式的時(shí)候冠摄,都手動(dòng)去修改每個(gè)組件的配置,組件少的情況下還可以接受几缭,組件多了會(huì)非常不方便河泳,下面就讓我們來(lái)聊聊如何實(shí)現(xiàn)兩種模式的自動(dòng)轉(zhuǎn)換。

  1. 首先年栓,聲明全局配置變量拆挥,來(lái)標(biāo)識(shí)module的屬性(app or library),如在工程目錄下的build.gradle文件中聲明布爾變量ext.isModule,true代表組件作為可獨(dú)立運(yùn)行的app某抓,false代表組件作為被依賴(lài)的library纸兔,如下所示

buildscript {
    ext.kotlin_version = '1.3.21'
    ext.isModule = true  //true-每個(gè)組件都是單獨(dú)的module,可獨(dú)立運(yùn)行  false-組件作為library存在
    repositories {
        google()
        jcenter()
    }
   
}

  1. 配置組件的build.gradle文件

//1
if (rootProject.ext.isModule) {
    //可獨(dú)立運(yùn)行的app
    apply plugin: 'com.android.application'
} else{
    //被依賴(lài)的library
    apply plugin: 'com.android.library'
}
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
apply plugin: 'kotlin-kapt'

android {
    compileSdkVersion 28
    defaultConfig {
      
      //applicationId "com.study.comp1" //2 如果沒(méi)有否副,默認(rèn)包名為applicationId
        minSdkVersion 19
        targetSdkVersion 28
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_7
        targetCompatibility JavaVersion.VERSION_1_7
    }
    //3
    sourceSets {
        main {
            if(rootProject.ext.isModule){
                manifest.srcFile 'src/main/java/module/AndroidManifest.xml'
            } else{
                manifest.srcFile 'src/main/java/library/AndroidManifest.xml'
                java {//移除module包下的代碼
                    exclude 'module'
                }
            }
        }
    }
}
    

上面是截取的組件gradle的部分代碼汉矿,包含了組件化需要配置的所有內(nèi)容,每一點(diǎn)都進(jìn)行了注釋

  • 注釋1:如上所述备禀,根據(jù)isModule的值负甸,來(lái)設(shè)置module的屬性流强,作為app or library
  • 注釋2:當(dāng)module屬性為library時(shí),不能設(shè)置applicationId呻待;當(dāng)為app時(shí)打月,如果未設(shè)置applicationId,默認(rèn)包名為applicationId蚕捉,所以為了方便奏篙,此處不設(shè)置applicationId
  • 注釋3:Android Studio會(huì)為每個(gè)module生成對(duì)應(yīng)的AndroidManifest.xml文件,聲明自身需要的權(quán)限迫淹、四大組件秘通、數(shù)據(jù)等內(nèi)容;當(dāng)module屬性為app時(shí)敛熬,其對(duì)應(yīng)的AndroidManifest.xml需要具備完整app所需要的所有配置肺稀,尤其是聲明Application和launch的Activity;當(dāng)module屬性為library時(shí)应民,如果每個(gè)組件都聲明自己的Application和launch的Activity话原,那在合并的時(shí)候就會(huì)發(fā)生沖突,編譯也不會(huì)通過(guò)诲锹,所以繁仁,就需要為當(dāng)前module重新定義一個(gè)AndroidManifest.xml文件,不聲明Application和launch的Activity归园,然后根據(jù)isModule的值指定AndroidManifest.xml的路徑黄虱,因此就有了注釋3處的寫(xiě)法。為了避免集成模式下的命名沖突庸诱,每個(gè)文件都以自身module名為前綴來(lái)命名會(huì)是一個(gè)很好的方法捻浦。下圖是該module的目錄
在這里插入圖片描述
  1. 在需要切換module屬性的時(shí)候改變步驟1處聲明的變量值,然后重新編譯即可

組件之間頁(yè)面跳轉(zhuǎn)(路由)

在組件化架構(gòu)中桥爽,不同的組件之間是平衡的默勾,不存在相互依賴(lài)的關(guān)系(可參考文章開(kāi)頭的架構(gòu)圖)。因此聚谁,假設(shè)在組件A中母剥,想要跳轉(zhuǎn)到組件B中的頁(yè)面,如果使用Intent顯式跳轉(zhuǎn)就行不通了形导,而且大家都知道环疼,Intent隱式跳轉(zhuǎn)管理起來(lái)非常不方便,所以Arouter出現(xiàn)了朵耕,并且有強(qiáng)大的技術(shù)團(tuán)隊(duì)支持炫隶,可以放心使用了。那么如何在組件化架構(gòu)中應(yīng)用Arouter呢阎曹?下面詳細(xì)來(lái)聊一聊

  1. 依賴(lài)處理

在common組件中將Arouter依賴(lài)進(jìn)來(lái)伪阶,并配置編譯參數(shù)煞檩;在業(yè)務(wù)組件中引入arouter編譯器插件,同時(shí)配置編譯器參數(shù)栅贴,下面是Common組件gradle文件的部分片段


//配置arouter編譯器參數(shù)斟湃,每個(gè)組件都需配置
kapt {
    arguments {
        arg("AROUTER_MODULE_NAME", project.getName())
    }
}

dependencies {
    //arouter api,只需在common組件中引入一次
    api('com.alibaba:arouter-api:1.4.1') {
        exclude group: 'com.android.support'
    }
    //arouter編譯器插件檐薯,每個(gè)組件都需引入
    kapt 'com.alibaba:arouter-compiler:1.2.2'
}

  1. 初始化及編碼實(shí)現(xiàn)

在組件架構(gòu)中凝赛,經(jīng)常會(huì)遇到組件需要使用全局Context的情況,當(dāng)組件屬性為app時(shí)坛缕,可以通過(guò)自定義Application實(shí)現(xiàn)墓猎;當(dāng)組件屬性為library時(shí),由于組件被app依賴(lài)赚楚,導(dǎo)致無(wú)法調(diào)用app的Application實(shí)例毙沾,而且自身不存在Application;所以宠页,這里給出的方案是在common組件中創(chuàng)建一個(gè)BaseApplication左胞,然后讓集成模式(組件模式)下的Application繼承BaseApplication,在BaseApplication中獲取全局Context,并做一些初始化的工作勇皇,這里需要初始化Arouter罩句,如下是在common組件中聲明的BaseApplication


abstract class BaseApplication : Application() {

    companion object {
        var _context: Application? = null
        //獲取全局Context
        fun getContext(): Application {
            return _context!!
        }
    }
    override fun onCreate() {
        super.onCreate()
        _context = this
        //初始化Arouter
        initARouter()
        //初始化其他第三方庫(kù)
    }
    private fun initARouter() {
        if (BuildConfig.DEBUG) {
            ARouter.openDebug()
            ARouter.openLog()
        }
        ARouter.init(this)
    }
    override fun onTerminate() {
        super.onTerminate()
        //清理Arouter注冊(cè)表
        ARouter.getInstance().destroy()
    }
}

根據(jù)Arouter的路由特性焚刺,初始化之后敛摘,就可以通過(guò)@Route注解注冊(cè)頁(yè)面,然后調(diào)用Arouter api實(shí)現(xiàn)頁(yè)面的跳轉(zhuǎn)了(這里所謂的跨組件頁(yè)面跳轉(zhuǎn)是指在集成模式下乳愉,而非組件模式下)兄淫,無(wú)關(guān)乎是否在同一個(gè)組件下面,
假設(shè)我們要從組件1頁(yè)面攜帶參數(shù)跳轉(zhuǎn)到組件2頁(yè)面蔓姚,請(qǐng)看下面示例


/**
 * 在組件2中通過(guò)@Route注解注冊(cè)該頁(yè)面
 */
@Route(path = "/comp2/msg",name = "我是組件2的MSGActivity")
class Comp2MsgActivity : BaseActivity() {
    //傳遞過(guò)來(lái)的參數(shù)
    @Autowired(name = "msg")
    @JvmField
    var msg: String? = null

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        //注入傳遞的參數(shù)
        ARouter.getInstance().inject(this)
        setContentView(R.layout.comp2_activity_msg)
        comp2_msg_msg.text = msg!!
    }
}

//在組件1中發(fā)起跳轉(zhuǎn)命令
ARouter.getInstance()
                    .build("/comp2/msg")
                    .withString("msg", "hello Im from Comp1")
                    .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
                    .navigation()

以上便完成了一次簡(jiǎn)單的跨越組件的頁(yè)面跳轉(zhuǎn)捕虽,僅僅是Arouter的基本使用而已。解決了組件間頁(yè)面跳轉(zhuǎn)的問(wèn)題后坡脐,我們來(lái)看看組件之間通信泄私、調(diào)用彼此服務(wù)的實(shí)現(xiàn)。

組件之間通信备闲、調(diào)用彼此服務(wù)

組件間通信功能和路由功能有著共通的地方晌端,即都是利用Arouter的基礎(chǔ)功能實(shí)現(xiàn),在Arouter驅(qū)動(dòng)層定義各個(gè)組件對(duì)外提供的接口恬砂,然后在組件自身模塊實(shí)現(xiàn)該接口咧纠,通過(guò)Arouter調(diào)用其他組件服務(wù)。假設(shè)我們?cè)诮M件2中需要調(diào)用組件1中的服務(wù)泻骤,可以總結(jié)為以下3點(diǎn)

  • 定義接口:在common組件中定義組件1對(duì)外提供的接口CompServer1漆羔,注意該接口類(lèi)型為Arouter模板類(lèi)型IProvider

/**
 * 組件1對(duì)外提供的接口
 */
interface CompServer1 : IProvider {
    fun showMsg(msg: String)
}

  • 實(shí)現(xiàn)接口:在comm1中實(shí)現(xiàn)上面定義的接口梧奢,并通過(guò)@Route注解注冊(cè)

@Route(path = "/comp1/server",name = "comp1對(duì)外提供的服務(wù)")
class CompServer : CompServer1 {
    var mContext: Context? = null
    override fun showMsg(msg: String) {
        Toast.makeText(mContext,msg,Toast.LENGTH_SHORT).show()
    }
    override fun init(context: Context?) {
        this.mContext = context!!
    }
}

  • 調(diào)用服務(wù):在完成組件1接口的定義和實(shí)現(xiàn)之后,在組件2中需要的地方調(diào)用該接口即可

val server1 = ARouter.getInstance().build("/comp1/server").navigation() as CompServer1
server1.showMsg("我從comp2吊起了comp1的接口")

有沒(méi)有感覺(jué)很簡(jiǎn)單演痒?亲轨?沒(méi)錯(cuò),就是這么簡(jiǎn)單嫡霞,趕緊去用吧!哈哈

打包混淆

說(shuō)到混淆瓶埋,有人可能會(huì)疑惑,如果在各個(gè)組件中混淆可不可以诊沪?不建議這樣混淆Q病!因?yàn)榻M件在集成模式下被gradle構(gòu)建成了release類(lèi)型的aar包端姚,如果在組件中進(jìn)行混淆晕粪,一旦代碼出現(xiàn)了bug,這個(gè)時(shí)候就很難根據(jù)日志去追蹤bug產(chǎn)生的原因渐裸,而且不同組件分別進(jìn)行混淆非常不方便維護(hù)和修改巫湘,這也是不推薦在業(yè)務(wù)組件中配置buildType(構(gòu)建類(lèi)型)的原因。

所以昏鹃,組件化項(xiàng)目的代碼混淆放在集成模式下的app殼工程尚氛,各個(gè)業(yè)務(wù)組件不配置混淆。集成模式下在app殼工程.gradle文件的release構(gòu)建模式下開(kāi)啟混淆洞渤,其他buildType配置和普通項(xiàng)目相同阅嘶,混淆文件放在app殼工程下,各個(gè)組件的代碼混淆均放在該混淆文件中载迄。

小結(jié)

以上讯柔,我們已經(jīng)逐一解決了組件化所面對(duì)的各個(gè)問(wèn)題,至此护昧,我們已經(jīng)搭建了一個(gè)簡(jiǎn)單的組件化架構(gòu)的項(xiàng)目魂迄,這一起感覺(jué)是在不知不覺(jué)中就實(shí)現(xiàn)了,并不是很難哦惋耙!現(xiàn)在捣炬,我們總結(jié)一下組件化的優(yōu)勢(shì)了

  • 解耦:將業(yè)務(wù)組件代碼90%與工程解耦,只所以是90%而非100%绽榛,是因?yàn)闃I(yè)務(wù)組件需要在common組件中聲明對(duì)外開(kāi)放的接口湿酸,那有沒(méi)有什么方式可以做到完全解耦呢?目前還沒(méi)有發(fā)現(xiàn)更好的辦法蒜田。稿械。。
  • 提高開(kāi)發(fā)效率:依賴(lài)解耦這一優(yōu)勢(shì)冲粤,團(tuán)隊(duì)成員可以只專(zhuān)注于自己負(fù)責(zé)的組件美莫,開(kāi)發(fā)效率更高页眯;而且,組件開(kāi)發(fā)過(guò)程中只需編譯自身的module厢呵,這樣大大縮短了編譯時(shí)長(zhǎng)窝撵,避免了漫長(zhǎng)的等待編譯局面。
  • 結(jié)構(gòu)清晰:在業(yè)務(wù)組件明確拆分的前提下襟铭,項(xiàng)目結(jié)構(gòu)變的異常清晰碌奉,非常方便全局掌控。

喜歡點(diǎn)擊+關(guān)注哦

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末寒砖,一起剝皮案震驚了整個(gè)濱河市赐劣,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌哩都,老刑警劉巖魁兼,帶你破解...
    沈念sama閱讀 211,290評(píng)論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異漠嵌,居然都是意外死亡咐汞,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,107評(píng)論 2 385
  • 文/潘曉璐 我一進(jìn)店門(mén)儒鹿,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)化撕,“玉大人,你說(shuō)我怎么就攤上這事约炎≈惨酰” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 156,872評(píng)論 0 347
  • 文/不壞的土叔 我叫張陵章钾,是天一觀的道長(zhǎng)墙贱。 經(jīng)常有香客問(wèn)我热芹,道長(zhǎng)贱傀,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,415評(píng)論 1 283
  • 正文 為了忘掉前任伊脓,我火速辦了婚禮府寒,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘报腔。我一直安慰自己株搔,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,453評(píng)論 6 385
  • 文/花漫 我一把揭開(kāi)白布纯蛾。 她就那樣靜靜地躺著纤房,像睡著了一般。 火紅的嫁衣襯著肌膚如雪翻诉。 梳的紋絲不亂的頭發(fā)上炮姨,一...
    開(kāi)封第一講書(shū)人閱讀 49,784評(píng)論 1 290
  • 那天捌刮,我揣著相機(jī)與錄音,去河邊找鬼舒岸。 笑死绅作,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的蛾派。 我是一名探鬼主播俄认,決...
    沈念sama閱讀 38,927評(píng)論 3 406
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼洪乍!你這毒婦竟也來(lái)了眯杏?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 37,691評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤壳澳,失蹤者是張志新(化名)和其女友劉穎役拴,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體钾埂,經(jīng)...
    沈念sama閱讀 44,137評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡河闰,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,472評(píng)論 2 326
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了褥紫。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片姜性。...
    茶點(diǎn)故事閱讀 38,622評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖髓考,靈堂內(nèi)的尸體忽然破棺而出部念,到底是詐尸還是另有隱情,我是刑警寧澤氨菇,帶...
    沈念sama閱讀 34,289評(píng)論 4 329
  • 正文 年R本政府宣布儡炼,位于F島的核電站,受9級(jí)特大地震影響查蓉,放射性物質(zhì)發(fā)生泄漏乌询。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,887評(píng)論 3 312
  • 文/蒙蒙 一豌研、第九天 我趴在偏房一處隱蔽的房頂上張望妹田。 院中可真熱鬧,春花似錦鹃共、人聲如沸鬼佣。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,741評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)晶衷。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間晌纫,已是汗流浹背驻龟。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,977評(píng)論 1 265
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留缸匪,地道東北人翁狐。 一個(gè)月前我還...
    沈念sama閱讀 46,316評(píng)論 2 360
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像凌蔬,于是被迫代替她去往敵國(guó)和親露懒。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,490評(píng)論 2 348

推薦閱讀更多精彩內(nèi)容

  • MVVMHabitComponent 關(guān)于Android的組件化砂心,相信大家并不陌生懈词,網(wǎng)上談?wù)摻M件化的文章,多如過(guò)江...
    goldze閱讀 5,179評(píng)論 2 22
  • 不怕跌倒辩诞,所以飛翔 組件化開(kāi)發(fā) 參考資源 Android組件化方案 為什么要組件化開(kāi)發(fā) 解決問(wèn)題 實(shí)際業(yè)務(wù)變化非常...
    筆墨Android閱讀 2,973評(píng)論 0 0
  • 問(wèn)題 在已經(jīng)開(kāi)發(fā)過(guò)幾個(gè)項(xiàng)目的童鞋,如果這時(shí)需要重新開(kāi)發(fā)一個(gè)新項(xiàng)目,是否需要自己重新搭建框架呢,還是從老項(xiàng)目中拷貝粘...
    8ba406212441閱讀 43,031評(píng)論 84 381
  • 上集回顧 上一篇文章解說(shuō)了模塊化以及組件译暂,插件化的概念抠忘。模塊化是一種解決項(xiàng)目分層的思想,組件化和插件化分別是其不同...
    DevCW閱讀 3,774評(píng)論 6 45
  • 概述 組件化緣由 記得剛開(kāi)始接觸Android開(kāi)發(fā)的時(shí)候外永,只知道MVC分層架構(gòu)崎脉,而且感覺(jué)Model,View以及C...
    wustor閱讀 1,884評(píng)論 0 12