天天看點

pyqt 擷取 UI 中元件_網易友品 Android 用戶端元件化演進

pyqt 擷取 UI 中元件_網易友品 Android 用戶端元件化演進
原文作者:簡書 - 四單老師

項目背景

主站業務經曆了長期的疊代維護,業務的增長同時帶來每個版本業務量繁重,疊代周期很快。同時團隊也在不斷的擴張,對應拆分了組内不同的業務線對接不同業務線的需求,最初的Android用戶端單一的設計架構已經逐漸不滿足快速的業務開發需求。曆經組内讨論開始對項目整理進行元件化的遷移,通過元件化的方式滿足不同業務線業務開發的穩定性,是疊代開發更靈活,組内協作開發效率得到提升。同時又有新的項目立項需要投入開發,一方面可以通過新項目實踐和推進元件化的遷移,另一方面也可以通過元件化拆分後的技術元件複用來更快的搭建和開發新的項目。

元件化的準備

技術準備

1. 主站最初的app項目隻有一個子產品,業務耦合嚴重,技術元件很難複用,是以我們采取的第一步是拆分部分基礎元件下沉為一個Base庫,盡量去解耦業務提取基礎技術元件達到多業務子產品的複用,也是為了支援新項目和主站項目多個app的技術支援。

2. 考慮元件化後的業務相對隔離,但是用戶端元件間需要建立通路,是以需要元件間通信的介入。我們采取的方式是路由、服務和全局通知。

3. 搭建路由庫支援,目的是解決業務元件實體隔離後的UI跳轉和通路,通過維護路由表的方式尋址到需要通路的業務元件UI。我們采取的是技術實作是通過注解給對應的業務UI比如LoginActivity上用注解申明對應的路由位址,在公共依賴的接口處公開維護這個路由位址常量,暴露給其他業務元件通過方位該位址來跳轉到對應的業務元件UI。

@Router
           

對應Act綁定上路由位址後,需要對路由的位址進行統一的收集管理。同時也為了支援某些服務動态下發的位址,政策是優先在本地的路由表進行比對,如果查詢到了該位址有對應的Native界面優先跳轉到Native的界面,未比對到則跳轉到由webView容器承載的網頁。目前我們采取的方式是通過APT自動生成對應路由注解後的activity的收集類。

//自動生成的類,命名規則是RouterGenerator+業務元件子產品名稱
           

然後再通過ASM的方式在編譯期對所有加載到工程裡面的子產品元件通過特定的規則進行上面路由輔助類的收集。

//收集路由位址
           

具體實作不再此展開了,此方式的好處就是可以根據需求加載需要的業務元件并且實作自動注冊和收集路由到路由表。如果覺得獨立開發路由庫的成本較高,也可以采取業界主流的一些路由庫比如ARouter等,基本類似。

4. 關于元件間服務通信的方式,目前采取的是暴露對應的服務接口供各個業務元件方調用。每個業務元件都會申明需要對外暴露提供的方法,并在自己的業務元件子產品内實作這些具體被調用的方法。對外接口庫根據子產品劃分,可以申明和維護通信間的一些資料類型,比如公開的資料model和對應需要通路的一些路由位址等。為了便于服務的動态收集,這些服務接口可以統一的繼承某個規則接口,然後采取上述路由的方式,對所有實作了該規則接口的服務接口統一的收集管理。

facade
           

剩下一些特點場景的業務,比如:登入成功後需要全局通知重新整理多個UI某個業務狀态的時候,目前采取EventBus的方式進行訂閱通知。

5. 在元件base庫一定下沉群組件間通信方式的确立,開始對元件的具體的拆分粒度進行劃分。大緻劃分為業務元件和技術元件兩部分。

元件化的拆分流程

拆分前的考慮

考慮新的項目投入的人力資源有限,并且需要快速的開發上線,同時業務也有重合的場景。是以當時采取的開發政策是将主站未元件化的代碼完全拷貝一份到新項目,并在此的基礎上進行改造。改造的原則必須遵循2個應用共建同一套BaseLib,但是由于主站的BaseLib裡面會耦合一些自身的業務元件,同時避免對BaseLib的修改影響到主站的業務開發而增加不必要的工作量。當時采取的政策是通過增加一層業務基礎元件庫來做新項目元件化拆分的緩沖層BaseCompatLib。

拆分過程

pyqt 擷取 UI 中元件_網易友品 Android 用戶端元件化演進

拆分過程中有很多業務元件共用的情況,結合當時的開發周期可以适當的去解耦部分業務元件重新劃分到對應拆分後的業務子產品中。如果時間有限,可以先挪到BaseCompatLib這個緩沖成暫時共用待後續再拆,進而避免對2個項目共用的Base庫頻繁修改帶來的負擔。

初期的業務子產品獨立編譯的配置方式,僅供參考:

//gradle.properties中申明編譯配置是否是獨立編譯
           

遇到的問題

拆分後的獨立子產品由于一些基礎服務的初始化仍停留在app殼工程,一些sdk或者初始化服務沒有統一的管理。優先級混亂并且耦合大量的業務邏輯,導緻業務子產品拆分後無法獨立運作,缺失對應元件所需服務的初始化步驟。開始改造初始化的業務,原理同自動收集一緻。

pyqt 擷取 UI 中元件_網易友品 Android 用戶端元件化演進
interface 
           

徹底元件化

pyqt 擷取 UI 中元件_網易友品 Android 用戶端元件化演進

元件庫的獨立釋出和維護

原有拆分的本地元件徹底分離出去,采取獨立釋出和維護的方式疊代更新。

  1. 建立git倉庫和本地元件項目,然後以module的方式将原有項目中的業務module導入到本地建立的項目中。推送該項目到git的獨立倉庫。(目前未采取git subModule的 方式管理,但大緻差不多)
  2. 建立的本地項目中再建立一個對應的接口工程用于對外暴露子產品中的業務通路。
project: 
           
  1. 添加打包aar釋出到maven倉庫的腳本用來獨立釋出login和login-facade子產品。
  2. 遵循對應的釋出規範,不同項目的app殼工程根據自身的業務需求進行對應的元件依賴,版本開發階段可采取snapshot的進行依賴。不同的業務元件也可以通過依賴其他不同的業務元件接口達到通路的目的。(如需實際運作,不光需要再接入接口庫還需要依賴對應的元件工程)
  3. 目前友品采取的是jenkins的打包釋出方式,僅供參考。

本地開發調試模式

在元件開發過程中,單純的依靠遠端方式依賴,對開發階段的頻繁修改不友好。是以我們采取依賴覆寫的方式,讓原有的依賴在編譯過程中替換掉遠端的版本改用本地的版本進行引用。

// 自定義const.gradle環境聲明
           

通過以上的方式讓Base的依賴從遠端替換為本地module的形式。開發階段就可以通過AS的refactor進行代碼的優化和重構,對本地Base修改後到Base的git分支進行對應的送出或MR合回主分支然後走規範的釋出打包流程。

元件版本依賴管理

元件項目中會有對Base或者接口庫的引用,對于Base我們可以選擇compileOnly的方式,也可以選擇直接依賴的方式。在內建到項目中後依賴會遵循gradle的依賴傳遞原則。特别注意:

  1. 避免環形依賴的産生。比如:facade -> base, base -> facade。遇到這種情況需要拆分所需依賴到另外一層。
  2. 在遠端依賴替換為本地依賴做開發修改時可能會遇到遠端依賴和本地依賴的沖突。比如:app -> login -> com.xxx:base; app -> home -> /localpath/base。 此時可以采取下面的方式進行依賴優先選擇本地的方式排除掉其他元件中的遠端依賴。
//setting.gradle
           

後續

到此為止基本上元件化就可以持續穩定的開發和維護了,元件化後也給團隊的開發效率帶來一定的提升,代碼也可以在一定可控的範圍内穩定的維護。并且在各自維護的元件中,大家也可以根據各自需求選擇合适自己業務的開發架構比如:mvp、LiveData、Rx等或者嘗試使用新語言Kotlin去編寫。解決業務耦合帶來的負擔同時也使各個元件達到了較高的可複用性,靈活的支援不同的應用項目,達到可插拔的方式內建開發。後續項目也會做一些優化,針對版本依賴的管理和簡化元件編譯和釋出內建的流程來提高協作開發的效率。

ASM自動收集參考:https://github.com/luckybilly/AutoRegister