醫動力Android基于CC組件化框架的探索與實踐

為什么要組件化?

醫動力App作為公司的核心產品已經有多年歷史了,隨著版本的不斷迭代,功能越來越多,代碼量越來越大,不可避免的會產生一下問題:

  • 業務越來越復雜,維護成本高;
  • 業務耦合度高,代碼越來越臃腫,團隊內部多人協作開發困難;
  • 編譯時間長,每修改一處代碼后都要重新編譯打包測試,導致非常耗時;
  • 開發測試困難,每次修改都必須打包整個項目運行.

因此,為了提高項目的可維護性和開發效率,組件化成為了必然.

組件化的目標

首先看看老版本的醫動力的項目工程結構

項目分為Doctor和Patient,它們之間公共的代碼放在common中,common中會依賴一些第三方的庫.隨著項目的迭代,Doctor和Patient里面的代碼會越來越耦合,因為單個module中僅僅是以包名作為功能的劃分,而包之間是可以隨意調用的.

AndroidStudio/IDEA是多模塊管理的,組件化的思路就是把不同的業務模塊拆分到各個子Module中,同時這些業務Module之間不會存在直接的調用,這樣當我們移除項目中的某個業務Module的時候不會影響整體的項目運行,如下圖所示:

可以看到有「ModuleIM」,「ModuleFollow」,「ModuleDiary」三個業務模塊,它們都會引用Common模塊而獲取一些基礎庫的支持,同時這些業務模塊是可以單獨運行的.后續會將更多的模塊獨立出來,完成徹底的組件化.

如何組件化?

Android的組件化的技術點主要在兩個方面:

  • 配置組件獨立運行的能力;
  • 組件之間的通信

第一點是通過在module的gradle.build中切換

apply plugin: 'com.android.application'
apply plugin: 'com.android.library',
復制代碼

并設置對應模式下加載的AndroidManifest.xml和src的路徑.

第二點由于組件之間是沒有直接依賴的關系的,要想讓它們通信就必須把它們注冊在一個公共的地方,這里可以通過路由,也可以通過注冊接口.

目前組件化的方案在網上有很多,由于組件化并不涉及Android系統級別的操作,因此是比較成熟穩定的.我們知道,組件化是需要花費大量時間和精力的,很難做到把項目徹底的拆分成組件,那有沒有一種方式可以讓我們不改動原有項目(改動很小)的情況下,將新功能進行組件化開發?

因此我們選擇了使用CC來進行組件化的改造

Component Caller(CC)介紹

業界首個支持漸進式組件化改造的Android組件化開源框架

引用自CC官方的兩張圖能讓我們很快的明白什么叫做漸進式組件化?

在漸進式組件化的方案中,可以先不用解耦,只需要讓單獨運行的組件能夠調用到主App中的功能即可。思路是這樣的:

  • 新業務以組件形式開發
  • 新組件需要調用的主App中的業務,在對應的模塊中創建一個組件類,對外暴露對應的服務,供其它組件調用,并不需要現在就將這個模塊解耦
  • 新組件通過跨App的方式調用主App中的組件
  • 主App也可以通過跨App的方式調用到單獨運行的組件App中的組件
  • 在同一個module中可以創建多個組件類,將來解耦時將對應的組件類移動到解耦后的module中即可

關于CC的技術實現細節可以查看其github主頁的wiki系列文章 github.com/luckybilly/…

組件化實踐

CC的集成

1.在項目的根gradle.build中加入:

buildscript {dependencies {... ...classpath 'com.billy.android:autoregister:1.4.1'}
}復制代碼

這個autoregister插件是用來在編譯期間動態掃描并修改class文件,實現組件的自動注冊,具體配置后面會提到

2.在Doctor和Patient這兩個主App的gradle.build中加入

ext.mainApp = true  //設置為true,表示此module為主app module,一直以application方式編譯
apply from: '../cc-setting.gradle'
復制代碼

cc-setting.gradle中主要進行了以下幾點操作:

  • 讀取local.properties文件中的配置來區分組件是否以獨立app的方式編譯;
  • 添加com.billy.android:cc:1.1.0依賴;
  • 自動注冊組件的配置

3.實現IComponent接口創建組件類

我們統一在Doctor和Patient中的exports包內創建App對外提供的組件,不同業務的組件放在創建在對于的類中管理

IComponent的實現也很簡單,提供一個模塊名稱name和對不同action的處理

主App的配置就這么多,接下來要新建一個組件Module

4.業務module的配置

這里需要設置module獨立運行時的applicationId,同時指定resourcePrefix資源前綴(防止不同模塊之間資源文件的沖突)

因為設置了module的獨立運行,就需要準備一份module在獨立運行模式下的AndroidManifest文件,路徑在src/main/debug下

5.業務module提供IComponent接口

和主App一樣,模塊要提供服務給其他模塊調用,需要提供實現IComponent的子類,因為業務module提供的服務會比較少且單一,我們將它放在包名下的ExportComponent下

7.主App設置需要依賴的module

dependencies {api fileTree(include: ['*.jar'], dir: 'libs')addComponent 'module_follow'addComponent 'module_diary'addComponent 'module_im'
}
復制代碼

通過addComponent方式添加依賴,其內部會根據業務module的運行模式決定是否依賴

6.設置業務module的運行模式

業務module的運行模式包括開發模式和集成模式

  • 開發模式:會以App的方式運行
  • 集成模式:打包在主App中

打開local.properties文件

module_follow=true
module_diary=true
module_im=false
復制代碼

設置模塊名稱等于true或者false(沒有設置則為false)

  • 當等于true則該模塊會以App運行,這時候打包主App的時候是不會把該模塊打包進去
  • 當等于false時則不能獨立運行,打包主App的時候會一起打包進去

運行調試

現在你可以將組件單獨運行起來了,但是由于業務組件是不包含登錄功能的,因此它是沒有用戶登錄狀態的,所以我們需要通過CC的組件調用去主App中獲取

補充一點,如果想要跨App調用首先需要打開CC的設置

CC.enableRemoteCC(true);
復制代碼

組件調用

CCResult result = CC.obtainBuilder("common").setActionName("httpInfo").addParam("type", type).build().call();String baseUrl = result.getDataItem("baseUrl");String token = result.getDataItem("token");
復制代碼

調用的方式很簡單,只需要指定模塊名稱和對應的Action,同時可以傳遞參數,以上代碼調用的是common模塊的action為httpInfo的組件.

同時支持同步和異步的調用,前一個例子是同步調用,異步調用需要傳入一個回調方法.

String callId = CC.obtainBuilder("Common").setActionName("httpInfo").addParam("type",type).build().callAsync(new IComponentCallback(){...});
復制代碼

被調用組件在處理完請求后,需要作出響應,看以下代碼:

public class HttpComponent implements IComponent {@Overridepublic String getName() {return "http";}@Overridepublic boolean onCall(CC cc) {String action = cc.getActionName();if(action.equals("action1")){CC.sendCCResult(cc.getCallId(),CCResult.success());return false;}else if(action.equals("action2")){String ccId = cc.getCallId();return true;}}
}復制代碼

注意onCall()方法的返回值,action1中返回的是false,而action2返回的是true,作用是:

  • false表示立即回調結果,這里需要調用 CC.sendCCResult(cc.getCallId(),CCResult.success() 告訴調用發返回成功
  • true則表示延遲回調結果,這時你可以拿著ccCallId,等到事情處理完后才調用CC.sendCCResult(cc.getCallId(),CCResult.success()

這有什么作用呢? 比如你在調用一個登錄組件去到登錄界面,只有登錄成功了才返回結果,這就需要延遲回調.

網絡請求組件化

項目中用到的網絡請求框架是okhttp+retrofit,我們希望不同module中使用不同的retrofit的Service實例,比如在Module_follow中我們會創建FollowService.java來處理當前模塊的網絡請求

在集成開發模式下我們可以通過組件調用去獲取主App中的Retrofit對象,我們只需要在主App中定一個name=http,action=getRetrofit的IComponent;

但在開發模式下,跨進程調用組件是傳輸不了Retrofit對象的,因為Android的跨進程只能傳輸Parcelable對象,這里我們可以在本module中提供一個相同名稱的IComponent,在里面去獲取主App的baseUrl和token,并創建新的Retrofit對象,這樣就可以透明的處理獲取Retrofit對象了.

為什么以上方式可行呢?因為CC在進行組件化調用的時候,會檢查當前模塊是否存在要調用的模塊,如果存在則會調用本地的,不存在才會去跨進程調用.最后我們可以把這些模擬操作抽到一個lib_mock的module里面復用.

組件化小結

組件化后帶來的一些變化:

  • 編譯時間明顯縮短
  • 開發人員之間可以通過模塊分工
  • 可以在模塊中嘗試新的技術而不擔心影響全局(Kotlin)

CC已知局限:

開發模式不能在Android8.0及以上環境運行,開發的時候可以使用虛擬機或者低版本的手機,集成模式不影響.

引用

CC:基于總線的android組件化開發框架
Android徹底組件化方案實踐

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/389670.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/389670.shtml
英文地址,請注明出處:http://en.pswp.cn/news/389670.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

使用協同過濾推薦電影

ALSO, ARE RECOMMENDER SYSTEMS INFLUENCING OUR TASTE??此外,推薦系統是否影響我們的口味? An excerpt on creating a movie recommender system similar to the OTT platforms.有關創建類似于OTT平臺的電影推薦系統的摘錄。 INTRODUCTION介紹 For…

423. 從英文中重建數字

423. 從英文中重建數字 給你一個字符串 s ,其中包含字母順序打亂的用英文單詞表示的若干數字(0-9)。按 升序 返回原始的數字。 例 1:輸入:s "owoztneoer" 輸出:"012"示例 2&#xf…

錦欣生殖獲戰略投資,華平、信銀領投,紅杉、藥明康德跟投

9月16日消息,錦欣生殖近日宣布已完成新一輪的戰略投資,本輪融資由原戰略股東華平投資及新引入的中信銀行旗下信銀投資領投,紅杉資本中國基金、藥明康德等跟投。完成本輪融資后,華平投資及信銀投資分別成為錦欣生殖的第二及第三大股…

數據暑假實習面試_面試數據科學實習如何準備

數據暑假實習面試Unfortunately, on this occasion, your application was not successful, and we have appointed an applicant who…不幸的是,這一次,您的申請沒有成功,我們已經任命了一位符合以下條件的申請人: Sounds famili…

兩道簡單的入門題

1&#xff09;  for循環求100以內奇數和 1 #include<stdio.h> 2 int main(){ 3 int ans0;//定義一個答案變量存儲答案 4 for(int i1;i<100;i)//用for從1循環到100&#xff0c;如果i%2&#xff01;0&#xff08;%是一種取余運算&#xff09; 5 if(…

1716. 計算力扣銀行的錢

1716. 計算力扣銀行的錢 Hercy 想要為購買第一輛車存錢。他 每天 都往力扣銀行里存錢。 最開始&#xff0c;他在周一的時候存入 1 塊錢。從周二到周日&#xff0c;他每天都比前一天多存入 1 塊錢。在接下來每一個周一&#xff0c;他都會比 前一個周一 多存入 1 塊錢。 給你 …

谷歌 colab_如何在Google Colab上使用熊貓分析

谷歌 colabRecently, pandas have come up with an amazing open-source library called pandas-profiling. Generally, EDA starts by df.describe(), df.info() and etc which to be done separately. Pandas_profiling extends the general data frame report using a singl…

【題解】HAOI2007分割矩陣

水題盛宴啦啦啦……做起來真的極其舒服&#xff0c;比某些毒瘤題好太多了…… 數據范圍極小 --> 狀壓 / 搜索 / 高維度dp&#xff1b;觀察要求的均方差&#xff0c;開始考慮是不是能夠換一下式子。我們用\(a_{x}\)來表示第 \(x\) 個矩陣的總值&#xff0c;則式子為&#xff…

Java之生成Pdf并對Pdf內容操作

雖說網上有很多可以在線導出Pdf或者word或者轉成png等格式的工具&#xff0c;但是我覺得還是得了解知道是怎么實現的。一來&#xff0c;在線免費轉換工具&#xff0c;是有容量限制的&#xff0c;達到一定的容量時&#xff0c;是不能成功導出的;二來&#xff0c;業務需求&#x…

邊際概率條件概率_數據科學家解釋的邊際聯合和條件概率

邊際概率條件概率Probability plays a very important role in Data Science, as Data Scientist regularly attempt to draw statistical inferences that could be used to predict data or analyse data better.P robability起著數據科學非常重要的作用&#xff0c;為數據科…

1822. 數組元素積的符號

1822. 數組元素積的符號 已知函數 signFunc(x) 將會根據 x 的正負返回特定值&#xff1a; 如果 x 是正數&#xff0c;返回 1 。 如果 x 是負數&#xff0c;返回 -1 。 如果 x 是等于 0 &#xff0c;返回 0 。 給你一個整數數組 nums 。令 product 為數組 nums 中所有元素值的…

java并發編程實戰:第十四章----構建自定義的同步工具

一、狀態依賴性管理 對于單線程程序&#xff0c;某個條件為假&#xff0c;那么這個條件將永遠無法成真在并發程序中&#xff0c;基于狀態的條件可能會由于其他線程的操作而改變1 可阻塞的狀態依賴操作的結構2 3 acquire lock on object state4 while (precondition does not ho…

關于之前的函數式編程

之前寫的函數式編程是我從 JavaScript ES6 函數式編程入門經典這本書里面整理的&#xff0c;然后只在第一篇里專門提到了&#xff0c;后面的話沒有專門提到&#xff0c;而且引用了書中大量的文字&#xff0c;所以我把掘金這里的文章都刪除了&#xff0c;然后在 CSDN 上面每一篇…

袋裝決策樹_袋裝樹是每個數據科學家需要的機器學習算法

袋裝決策樹袋裝樹木介紹 (Introduction to Bagged Trees) Without diving into the specifics just yet, it’s important that you have some foundation understanding of decision trees.尚未深入研究細節&#xff0c;對決策樹有一定基礎了解就很重要。 From the evaluatio…

[JS 分析] 天_眼_查 字體文件

0. 參考 js分析 貓_眼_電_影 字體文件 font-face 1. 分析 1.1 定位目標元素 1.2 查看網頁源代碼 1.3 requests 請求提取得到大量錯誤信息 對比貓_眼_電_影抓取到unicode編碼&#xff0c;天_眼_查混合使用正常字體和自定義字體&#xff0c;難點在于如何從 紅 轉化為 美。 一開始…

深入學習Redis(4):哨兵

前言在 深入學習Redis&#xff08;3&#xff09;&#xff1a;主從復制 中曾提到&#xff0c;Redis主從復制的作用有數據熱備、負載均衡、故障恢復等&#xff1b;但主從復制存在的一個問題是故障恢復無法自動化。本文將要介紹的哨兵&#xff0c;它基于Redis主從復制&#xff0c;…

1805. 字符串中不同整數的數目

1805. 字符串中不同整數的數目 給你一個字符串 word &#xff0c;該字符串由數字和小寫英文字母組成。 請你用空格替換每個不是數字的字符。例如&#xff0c;“a123bc34d8ef34” 將會變成 " 123 34 8 34" 。注意&#xff0c;剩下的這些整數為&#xff08;相鄰彼此至…

經天測繪測量工具包_公共土地測量系統

經天測繪測量工具包部分-鄉鎮第一師 (Sections — First Divisions of Townships) The PLSS Townships are typically divided into 36 Sections (nominally one mile on a side), but in the national standard this feature is called the first division because Townships …

洛谷 P4012 深海機器人問題【費用流】

題目鏈接&#xff1a;https://www.luogu.org/problemnew/show/P4012 洛谷 P4012 深海機器人問題 輸入輸出樣例 輸入樣例#1&#xff1a; 1 1 2 2 1 2 3 4 5 6 7 2 8 10 9 3 2 0 0 2 2 2 輸出樣例#1&#xff1a; 42 說明 題解&#xff1a;建圖方法如下&#xff1a; 對于矩陣中的每…

day5 模擬用戶登錄

_user "yangtuo" _passwd "123456"# passd_authentication False #flag 標志位for i in range(3): #for 語句后面可以跟else&#xff0c;但是不能跟elifusername input("Username:")password input("Password:")if username _use…