溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

程序員不可以錯(cuò)過(guò)的Android組件化神器-ServicePool!

發(fā)布時(shí)間:2020-08-13 14:57:52 來(lái)源:ITPUB博客 閱讀:164 作者:yilian 欄目:移動(dòng)開(kāi)發(fā)

介紹

組件化開(kāi)發(fā)過(guò)程中,隨著組件越來(lái)越多,組件的之前的交互就會(huì)變得非常的復(fù)雜,此時(shí)組件間通信變得尤其的重要, ServicePool就是為組件化而生,用最簡(jiǎn)單的方式進(jìn)行組件間通信。

使用依賴注入,按需靈活注入組件。同時(shí)支持組件熱插拔,達(dá)到組件即插即用的效果??膳渲媒M件生命周期,做到組件按需創(chuàng)建和及時(shí)回收,充分利用懶加載的思想,有效解決組件初始化耗時(shí)導(dǎo)致的 app啟動(dòng)速度問(wèn)題。

ServicePool包含有 Activity路由, 組件路由等等最常用的組件化能力。除此之外,組件化開(kāi)發(fā)過(guò)程中有沒(méi)有遇到過(guò)想使用某個(gè)已有的類,比如一個(gè)工具類的時(shí)候,發(fā)現(xiàn)這個(gè)工具類在當(dāng)前類的上層,無(wú)法直接依賴和引用,而修改這個(gè)工具類的層級(jí)又會(huì)牽一發(fā)而動(dòng)全身的問(wèn)題?有沒(méi)有想要一個(gè)差異響應(yīng)的能力,在不同的組件中或者環(huán)境下,有著不同的響應(yīng)方式?有沒(méi)有想要一個(gè)自適應(yīng)場(chǎng)景的能力,自動(dòng)適應(yīng)當(dāng)前環(huán)境(比如 Java還是 Android環(huán)境,比如 Debug環(huán)境還是 Release環(huán)境等等),從而使用最合適的功能。又有沒(méi)有想過(guò)如何讓組件做到像USB接口一樣插上就能直接使用,拔掉也不影響主體功能的即插即用的效果。等等...。下面就來(lái)具體介紹一下這個(gè)組件化神器—— ServicePool

ServicePool基礎(chǔ)能力

程序員不可以錯(cuò)過(guò)的Android組件化神器-ServicePool!

如上圖所示:

  1. 組件 A, B是兩個(gè)互不依賴的組件, A, B不能直接通信
  2. 組件 A, B分別通過(guò) AService, BService對(duì)外提供服務(wù)
  3. 組件 A, B的接口協(xié)議存放在組件服務(wù)池 pool, 分別是接口IA, IB
  4. 當(dāng)組件B需要組件A的服務(wù)時(shí),組件B使用IA接口向 ServicePool申請(qǐng), 由 ServicePool創(chuàng)建并返回 aService給組件B, 此時(shí)組件 b可以使用 aService的服務(wù)了
  5. 同理, 組件 A使用 IBServicePool申請(qǐng) bService
  6. aService, bServiceServicePool創(chuàng)建和管理
  7. 所有 Service對(duì)象的優(yōu)先級(jí)生命周期可以通過(guò) @Service注解配置
  /**
   * 服務(wù)池pool中
   *
   * IA.java
   */
  public interface IA {  void aName();
  }  /**
   * 服務(wù)池pool
   *
   * IB.java
   */
  public interface IB {  void bName();
  }
  /**
   * 組件A
   *
   * AService.java
   */
  @Service
  public class AService implements IA {  @Override
  public String aName() {  return "A Service";
      }
  }
  /**
   * 組件B
   * 
   * BService.java
   */
  @Service
  public class BService implements IB {  @Override
  public String bName() {  return "B Service";
      }
  }
  組件A中執(zhí)行:
  IB b = ServicePool.getService(IB.class);
  System.out.println("I'm A Service, I can get " + b.bName());
  輸出: 
  I'm A Service, I can get B Service
  組件B中執(zhí)行:
  IA a = ServicePool.getService(IA.class);
  System.out.println("I'm B Service, I can get " + a.aName());
  輸出:
  I'm B Service, I can get A Service

依賴注入(DI)

由于所有示例涉及到依賴注入,這里提前對(duì) ServicePool的依賴注入做個(gè)說(shuō)明。和其他注入框架不同, ServicePool的注入方式很簡(jiǎn)單,只有一種注入方式就是直接通過(guò)類注入。

  @Service
  public class AImpl implements IA {  @Override
  public String aName() {  return "A Impl"
      }
  }

ServicePool就是一個(gè)注入容器。最后通過(guò) ServicePool. getService(IA.class)方法注入對(duì)象, 也可以通過(guò) @Service標(biāo)記成員變量的方式注入,這兩個(gè)方法等價(jià)。

  public class MainActivity extends AppcompatActivity {  /**
       * 等價(jià)于
       * IA = ServicePool.getService(IA.class);
       */
  @Service
  private IA a; 
  @Override
  public void onCreate(Bundle savedInstanceState) {
          System.out.println(a.getName()); //輸出 A Service
      }
  }

ServicePool注入對(duì)象時(shí),會(huì)根據(jù) Service配置的生命周期類型 (scope)和優(yōu)先級(jí)來(lái)決定當(dāng)前是創(chuàng)建還是直接返回緩存對(duì)象。

指定Service優(yōu)先級(jí),按優(yōu)先級(jí)順序返回

程序員不可以錯(cuò)過(guò)的Android組件化神器-ServicePool!

如果IA有多個(gè)實(shí)現(xiàn),如上圖所示, ServicePool會(huì)比較每個(gè)實(shí)現(xiàn)優(yōu)先級(jí),來(lái)決定最
終返回IA的哪個(gè)實(shí)現(xiàn)

  1. @Service注解標(biāo)記一個(gè)實(shí)現(xiàn)類時(shí)候可以通過(guò)參數(shù)priority指定這個(gè)實(shí)現(xiàn)類的優(yōu)先級(jí)
  2. 優(yōu)先級(jí)值越大優(yōu)先級(jí)越高,  ServicePool默認(rèn)會(huì)返回優(yōu)先級(jí)最高的實(shí)現(xiàn)類對(duì)象
  3. 如果多個(gè)實(shí)現(xiàn)類優(yōu)先級(jí)相同,那么返回會(huì)有不確定性
  4. 也可以直接指定具體使用哪個(gè)實(shí)現(xiàn)類,如 ServicePool. getService(AService1.class)將會(huì)返回一個(gè) AService1對(duì)象
  /**
   * 服務(wù)池pool中
   * 
   * IPriorityService.java
   */
  public interface IPriorityService {  int getPriority();
  }
  /**
   * 組件A中
   * 
   * PriorityService1.java
   * PriorityService2.java
   */
  @Service(priority = 1)  public class PriorityService1 implements IPriorityService {  @Override
  public int getPriority() {  return 1;
      }
  }  @Service(priority = 2)  public class PriorityService2 implements IPriorityService {  @Override
  public int getPriority() {  return 2;
      }
  }
  組件B中執(zhí)行:
  IPriorityService priorityService = ServicePool.getService(IPriorityService.class);
  System.out.println("priority is " + priorityService.getPriority());
      priorityService = ServicePool.getService(PriorityService1.class);
  System.out.println("priority is " + priorityService.getPriority());
      priorityService = ServicePool.getService(PriorityService2.class);
  System.out.println("priority is " + priorityService.getPriority());
  輸出:
     priority is 2
     priority is 1
     priority is 2

典型應(yīng)用場(chǎng)景

  1. Java Library組件和 Android Library組件使用不同的服務(wù), 如 classloader等等。
  2. debug環(huán)境, release環(huán)境或者不同的 productFlavor使用不同的服務(wù), 如 loggerMock等等
  3. 不同的業(yè)務(wù)場(chǎng)景使用不同的服務(wù)

給服務(wù)對(duì)象指定生命周期

每個(gè)由 ServicePool創(chuàng)建的 service對(duì)象都有各自生命周期, service對(duì)象的生命周期由 ServicePool管理, 并由 @Service注解配置生命周期類型。

  1. Serviceoncetempglobal三種生命周期類型.
  2. 指定 Service的生命周期為 once, @Service(scope=IService.Scope.once),每次 ServicePool.getService()都會(huì)創(chuàng)建一個(gè)新的對(duì)象,對(duì)象使用后隨 gc自動(dòng)被回收,  scope默認(rèn)為 once
  3. 指定 Service的生命周期為 temp, @Service(scope=IService.Scope.temp), ServiceWeakReference緩存,只適用無(wú)狀態(tài)服務(wù)。
  4. 指定 Service的生命周期為 global, @Service(scope=IService.Scope.global),每次 ServicePool.getService()拿到的都是同一個(gè)對(duì)象, App運(yùn)行期間不會(huì)被回收
  組件A中  /**
   * 
   * OnceService.java
   */
  @Service(scope = IService.Scope.once)  public class OnceService implements LifecycleService {
  }  /**
   * 
   * TempService.java
   */
  @Service(scope = IService.Scope.temp)  public class TempService implements LifecycleService {
  }  /**
   * 
   * GlobalService.java
   */
  @Service(scope = IService.Scope.global)  public class GlobalService implements LifecycleService {
  }
 組件B中執(zhí)行:    System.out.println(ServicePool.getService(OnceService.class) == ServicePool.getService(OnceService.class));//System.out.println(ServicePool.getService(TempService.class) == ServicePool.getService(TempService.class));//不可靠    System.out.println(ServicePool.getService(GlobalService.class) == ServicePool.getService(GlobalService.class));輸出:falsetrue

支持通過(guò)path查找Service

  /**
   * 服務(wù)池pool中
   * 
   * IPathService.java
   */
  public interface IPathService {  String pathServiceName();
  }
  /**
   * 組件A中
   * 
   * PathService
   */
  @Service(path = "pathService")  public class PathService implements IPathService {  @Override
  public String pathServiceName() {  return "Path Service";
      }
  }

IPathService是任意定義的接口,它可以有一個(gè)或多個(gè)實(shí)現(xiàn)類,只要在實(shí)現(xiàn)類上加 @Service注解并指定 path屬性。我們就可以通過(guò) ServicePool.getService(path)來(lái)找到或者創(chuàng)建他的實(shí)現(xiàn)類對(duì)象。

  組件B中執(zhí)行:
      IPathService pathService = ServicePool.getService("pathService");
      System.out.println(pathService.pathServiceName());
  輸出:
      Path Service
典型應(yīng)用場(chǎng)景:
  1. activity路由
  2. 混合開(kāi)發(fā)中,可以通過(guò) path將橋接方法分發(fā)到對(duì)應(yīng)執(zhí)行器

組件初始化

app開(kāi)發(fā)過(guò)程中,肯定少不了對(duì)組件進(jìn)行初始化,無(wú)論是內(nèi)部組件還是引用外部庫(kù),很多都需要執(zhí)行初始化操作。常規(guī)的方式是所有初始化操作都是放到 ApplicationonCreate()/onAttachBaseContext()方法中執(zhí)行。組件有很多而 Application只有 1個(gè), 如何讓每個(gè)組件都可以擁有它自己的初始化類呢? ServciePool中有一個(gè) @Init注解,任何被 @Init注解標(biāo)記的 Service類被認(rèn)為是一個(gè)需要執(zhí)行操作初始化操作的 Service類, 同時(shí)這個(gè) Service類需要實(shí)現(xiàn) IInitService接口。

  @Init(lazy = false) //lazy = false表示禁用懶加載,則該Service會(huì)隨Application初始化而初始化
  @Service
  public class InitService implements IInitService {  @Override
  public void onInit() {  //do something.
      }
  }

如果初始化組件想要隨 Application初始化而初始化,需要將 @Init注解的 lazy賦值為 false,表示禁用懶加載。除了 lazy屬性, @Init注解還有 asyncdependencies兩個(gè)屬性。 async屬性顧名思義是異步執(zhí)行, async默認(rèn)為 false,設(shè)置為 true表示該組件初始化會(huì)在異步線程執(zhí)行。 dependencies可以傳遞一個(gè)初始化組件類數(shù)組,表示當(dāng)前組件初始化依賴這個(gè)數(shù)組中的所有組件。 ServicePool會(huì)先初始化數(shù)組中的組件再去執(zhí)行當(dāng)前組件的初始化。

  @Init
  @Service
  public class InitService1 implements IInitService {  @Override
  public void onInit() {
          System.out.println("Service 1 Inited!!!");
      }
  }  @Init
  @Service
  public class InitService2 implements IInitService {  @Override
  public void onInit() {
          System.out.println("Service 2 Inited!!!");
      }
  }  @Init(lazy = false, dependencies=[InitService1.class, InitService2.class])  @Service
  public class InitService3 implements IInitService {  @Override
  public void onInit() {
          System.out.println("Service 3 Inited!!!");
      }
  }

ServicePool的初始化在
https://juejin.im/post/5e1ef261f265da3e0535f10a這篇文章的最后中有實(shí)際應(yīng)用,也可做為示例參考。

組件懶加載機(jī)制 & 禁用懶加載

所有初始化操作都隨 Application啟動(dòng)執(zhí)行,一方面會(huì)導(dǎo)致 Application非常臃腫,另一方面雖然單個(gè)組件初始化時(shí)長(zhǎng)很短,但 n多個(gè)組件初始化時(shí)長(zhǎng)結(jié)合在了一起就會(huì)導(dǎo)致啟動(dòng)時(shí)間超長(zhǎng)。懶加載是 ServicePool的核心思想。所有組件只有在第一次被使用時(shí)才會(huì)被創(chuàng)建和執(zhí)行初始化。而不是集中在 Application初始化過(guò)程。分散初始化從而減輕 App啟動(dòng)壓力。舉個(gè)????微信分享是很常用的功能,我們以微信分享為例, WXShareManager用來(lái)助力微信分享相關(guān)操作。

  @Init
  @Service
  public class WXShareManager implement IInitService {  public static final String appId = "wx499fa9b1ba4a93db";  public static final String userName = "gh_6619a14a139d";  @Override
  public void onInit() {
          IWXAPI wxApi = WXAPIFactory.createWXAPI(mContext, null);
          wxApi.registerApp(appId);
      }  public void share(...) {  //do wx share.
      }
  }

shareManager注入對(duì)象的時(shí)候初始化操作會(huì)被執(zhí)行。

  public class ShareActivity extends AppcompatActivity {  @Service
  private WXShareManager shareManager;//此時(shí)會(huì)觸發(fā)WXShareManager的onInit初始化。
    ...  void onClick(View v) {
          shareManager.share(...);
      }
  }

組件熱插拔

未完待續(xù)....

Activity路由

未完待續(xù)....

star下我的GitHub: https://github.com/Meng997998/AndroidJX,給文章點(diǎn)個(gè)贊一起學(xué)習(xí)!

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI