组件化实践详解(二)
在上一篇文章《組件化實踐詳解(一)》中我們介紹了組件化實踐的目標和實踐步驟,本文繼續說說關于組件化實踐遇到的問題及思考。
1、組件內的架構設計
這條本來我是不想寫的,但是很多組件化的文章里都會費盡心思的寫組件內的架構設計。
那我也談一談我的看法:首先回歸初心,想想組件化的目的,為了各個業務組件可以單獨運行。劃重點:目的是單獨運行,把之前在App Module的代碼挪到自己單獨的Module,然后能夠獨立運行;而不是大面積重構!!我也相信對于大部分團隊,實際上并沒有很多的時間去做重構,尤其是在做組件化的過程中同時大面積重構,確定做了風險評估嗎?
對于組件化的整體設計,需要遵循制定的規則,但是對于組件內的架構設計,實際上不需要特殊的要求,代碼你愛怎么寫就可以怎么寫,不管你使用MVC、MVP還是MVVM,根據各自情況合理選擇就好了。這個話題本來就不屬于組件化項目的范疇。
2、調試方式
假如之前的幾步我們都順利完成,現在整個Project已經變成了下圖整個樣子。
那我們的Module要怎么才能跑起來呢?
二者結合呢?借助馮大大在MDCC上的分享,將Module分為兩個模式:Release模式和Debug模式,Release模式下作為Library,供宿主依賴;而在Debug模式下則作為Application工程,自己單獨運行。
build.gradle中根據gradle中的一個屬性值來判斷處于哪種模式下:
if (isDebug.toBoolean()) {apply plugin: 'com.android.application'} else {apply plugin: 'com.android.library'}sourceSets {main {if (isDebug.toBoolean()) {manifest.srcFile 'src/main/debug/AndroidManifest.xml'} else {manifest.srcFile 'src/main/release/AndroidManifest.xml'}}} 復制代碼在Release中的AndroidManifest配置默認啟動的主Activity。
這樣一來調試的問題也就解決了。但是實際上這僅僅是一個Demo雛形,我們思考幾個帶出來的問題:
如何對這個情況做優化:各個獨立Module提供穩定版本的aar!
- 單獨的業務組件開發完成之后,記錄一個版本號同時提供一個穩定的aar;
- 別的依賴模塊直接去compile需要的業務組件的aar即可;
- Host宿主則是compile這些業務組件穩定的aar;
- 依賴于穩定的aar,那么自己的業務組件開發并不會影響到別人,而且Build的時候宿主也不會出錯;
- 針對眾多的aar包,最好建一個maven倉庫來統一管理;
- 生成及上傳aar包這步,可以寫個腳本幫忙生成及上傳;
3、工程化經驗
以下介紹些關于工程化的經驗
3.1 Application
部分業務組件一定會遇到依賴一些三方組件需要提前初始化的情況,正常我們的做法都是在應用的Application中做的。此時我們在獨立的Module開發,沒有了應用的Application,那么可以自己創建一個Module的Application,以下提幾種實現的思考:
備注:而怎么判斷調用業務Module呢?兩個場景:UI跳轉或者方法調用,這兩種判斷可以使用路由框架來協助。
3.2 Application與Tinker的兼容
Tinker作為熱修復的可靠解決方案,想必很多App都會集成,但是Tinker集成稍繁瑣的地方就在于:為了確保Application也能修復,需要改造Application,改造完成之后打的包出來真正的Application已經被修改,而寫上了我們邏輯的Application實際上變成了一個普通類,只是相應方法被真正的Application調用!
那我想把Tinker這個模塊也單獨作為一個Module來使用,能行嗎?首先來思考一個問題:Application要在哪里,Library中還是Host?
答案是Library中,因為各個Module中可能會存在不方便獲取Context的場景,解決方案之一就是使用Application的Context。假設Application放在Host中,那Module肯定是無法使用的。當然剛剛我們說到Module自己的Application,但是別忘了如果Module沒有呢?
把Application放到Library中也不是說移就能移:
- 正常情況下我們會發現Host Application中也有一大堆的邏輯或者是組件初始化,而這些組件要全被移出去還需要 a long long time;
- 代碼中有一大堆通過Host Application拿到的Context,現在忽然移出去,必定一大堆報錯;
面對如此抉擇,那到底是移還是不移?一個好方法是原來Host的Application只做較小改動:并不移出來之前的各種邏輯和組件,而是作為一個普通類,在Library中的Application方法執行時去回調相應Host Application的方法;隨后在組件化的過程中逐漸的移出來這些業務和組件。這樣的改動成本最小又滿足了當下的需要。
3.3 資源沖突
在拆分出來多個Module或者新建Module進行開發,新建資源的時候可能會有命名的沖突,對Gradle熟悉的同學可能會表示使用resourcePrefix來進行限定,但是坦白說效果一般,倒是不如在編碼規范中加上一條以相應Module的標示作為命名的前綴。
3.4 ButterKnife的使用
ButterKnife——相信很多同學都用過,這是一個注解框架,一般在綁定View的時候使用,減少了很多無意義的代碼。在正常開發中我們用起來也是6的飛起!然而當ButterKnife跑在Library工程中的時候各種Build失敗就出現了:原因在于Android Library中的R文件字段并不是常量,Module在Debug模式下是Application工程可以開心玩耍,等真正集成的時候切換回Release模式就呵呵噠了。
在ButterKnife8.0之后也支持了在Library中使用,解決方式就是同時生成了一個R2,這個就是常量,因而可以在Library工程中使用。
推薦使用Android ButterKnife Plugin Plus插件,方便的一鍵生成然后將R更改為R2;或者自己仿照去寫一個AS插件,直接生成R2。
備注:同時注意R2只能使用在注解中,因而點擊事件要寫成這樣:
@OnClick(R2.id.tv_back_selerole)public void onClick(View view) {if (view.getId() == R.id.tv_back_selerole) {dealBack();}} 復制代碼3.5 避免過大的基礎庫
這個問題的引出是在組件化相對成熟的階段,已經初步完成了我們的預期目標,但是細化的過程中逐漸意識到一個問題:Library庫越來越大,其實單獨的一個Module并不會需要那么多的組件,但是單獨Module運行的時候還是被引用上了,也會拖慢單獨Module的執行速度。
于是我們提出了另外一個名詞:去中心化。將基礎庫進行細粒度的拆分,將開發中一定會用到的例如網絡請求、EventBus、公共類等放在了Library中,而將別的不常用三方組件如地圖等移出去,只供需要的Module去依賴,而普通的Module則只依賴常用的Library。
這樣可以有效的避免Library逐漸變得膨脹,也給各Module只去依賴自己需要的特定Library能力。
4、組件化成效
歷經千辛萬苦我們對項目做了組件化實踐,那究竟收獲了哪些好處呢?
- 代碼結構層次清晰明了;
- 組件間界限清晰、有明確邊界,低耦合;
- 開發過程體驗好,快速編譯;
- 版本周期內沒有動到的組件快速回歸;
- 方便A/BTest;
廣告時間
今日頭條各Android客戶端團隊招人火爆進行中,各個級別和應屆實習生都需要,業務增長快、日活高、挑戰大、待遇給力,各位大佬走過路過千萬不要錯過!
本科以上學歷、非頻繁跳槽(如兩年兩跳),歡迎加我的微信詳聊:KOBE8242011
總結
以上是生活随笔為你收集整理的组件化实践详解(二)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 记一次解决 quill(vue-quil
- 下一篇: 8Manage PPM助力中投证券 项目