程序员不可以错过的Android组件化神器-ServicePool!

介绍

组件化开发过程中,随着组件越来越多,组件的之前的交互就会变得非常的复杂,此时组件间通信变得尤其的重要, ServicePool就是为组件化而生,用最简单的方式进行组件间通信。

创新互联公司是一家专业提供裕民企业网站建设,专注与网站建设、网站设计HTML5建站、小程序制作等业务。10年已为裕民众多企业、政府机构等服务。创新互联专业网站制作公司优惠进行中。

使用依赖注入,按需灵活注入组件。同时支持组件热插拔,达到组件即插即用的效果。可配置组件生命周期,做到组件按需创建和及时回收,充分利用懒加载的思想,有效解决组件初始化耗时导致的 app启动速度问题。

ServicePool包含有 Activity路由, 组件路由等等最常用的组件化能力。除此之外,组件化开发过程中有没有遇到过想使用某个已有的类,比如一个工具类的时候,发现这个工具类在当前类的上层,无法直接依赖和引用,而修改这个工具类的层级又会牵一发而动全身的问题?有没有想要一个差异响应的能力,在不同的组件中或者环境下,有着不同的响应方式?有没有想要一个自适应场景的能力,自动适应当前环境(比如 Java还是 Android环境,比如 Debug环境还是 Release环境等等),从而使用最合适的功能。又有没有想过如何让组件做到像USB接口一样插上就能直接使用,拔掉也不影响主体功能的即插即用的效果。等等...。下面就来具体介绍一下这个组件化神器—— ServicePool

ServicePool基础能力

程序员不可以错过的Android组件化神器-ServicePool!

如上图所示:

  1. 组件 A, B是两个互不依赖的组件, A, B不能直接通信
  2. 组件 A, B分别通过 AService, BService对外提供服务
  3. 组件 A, B的接口协议存放在组件服务池 pool, 分别是接口IA, IB
  4. 当组件B需要组件A的服务时,组件B使用IA接口向 ServicePool申请, 由 ServicePool创建并返回 aService给组件B, 此时组件 b可以使用 aService的服务了
  5. 同理, 组件 A使用 IBServicePool申请 bService
  6. aService, bServiceServicePool创建和管理
  7. 所有 Service对象的优先级生命周期可以通过 @Service注解配置
  /**
   * 服务池pool中
   *
   * IA.java
   */
  public interface IA {  void aName();
  }  /**
   * 服务池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中执行:
  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中执行:
  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)

由于所有示例涉及到依赖注入,这里提前对 ServicePool的依赖注入做个说明。和其他注入框架不同, ServicePool的注入方式很简单,只有一种注入方式就是直接通过类注入。

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

ServicePool就是一个注入容器。最后通过 ServicePool. getService(IA.class)方法注入对象, 也可以通过 @Service标记成员变量的方式注入,这两个方法等价。

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

ServicePool注入对象时,会根据 Service配置的生命周期类型 (scope)和优先级来决定当前是创建还是直接返回缓存对象。

指定Service优先级,按优先级顺序返回

程序员不可以错过的Android组件化神器-ServicePool!

如果IA有多个实现,如上图所示, ServicePool会比较每个实现优先级,来决定最
终返回IA的哪个实现

  1. @Service注解标记一个实现类时候可以通过参数priority指定这个实现类的优先级
  2. 优先级值越大优先级越高,  ServicePool默认会返回优先级最高的实现类对象
  3. 如果多个实现类优先级相同,那么返回会有不确定性
  4. 也可以直接指定具体使用哪个实现类,如 ServicePool. getService(AService1.class)将会返回一个 AService1对象
  /**
   * 服务池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中执行:
  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

典型应用场景

  1. Java Library组件和 Android Library组件使用不同的服务, 如 classloader等等。
  2. debug环境, release环境或者不同的 productFlavor使用不同的服务, 如 loggerMock等等
  3. 不同的业务场景使用不同的服务

给服务对象指定生命周期

每个由 ServicePool创建的 service对象都有各自生命周期, service对象的生命周期由 ServicePool管理, 并由 @Service注解配置生命周期类型。

  1. Serviceoncetempglobal三种生命周期类型.
  2. 指定 Service的生命周期为 once, @Service(scope=IService.Scope.once),每次 ServicePool.getService()都会创建一个新的对象,对象使用后随 gc自动被回收,  scope默认为 once
  3. 指定 Service的生命周期为 temp, @Service(scope=IService.Scope.temp), ServiceWeakReference缓存,只适用无状态服务。
  4. 指定 Service的生命周期为 global, @Service(scope=IService.Scope.global),每次 ServicePool.getService()拿到的都是同一个对象, App运行期间不会被回收
  组件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中执行:    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

支持通过path查找Service

  /**
   * 服务池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是任意定义的接口,它可以有一个或多个实现类,只要在实现类上加 @Service注解并指定 path属性。我们就可以通过 ServicePool.getService(path)来找到或者创建他的实现类对象。

  组件B中执行:
      IPathService pathService = ServicePool.getService("pathService");
      System.out.println(pathService.pathServiceName());
  输出:
      Path Service
典型应用场景:
  1. activity路由
  2. 混合开发中,可以通过 path将桥接方法分发到对应执行器

组件初始化

app开发过程中,肯定少不了对组件进行初始化,无论是内部组件还是引用外部库,很多都需要执行初始化操作。常规的方式是所有初始化操作都是放到 ApplicationonCreate()/onAttachBaseContext()方法中执行。组件有很多而 Application只有 1个, 如何让每个组件都可以拥有它自己的初始化类呢? ServciePool中有一个 @Init注解,任何被 @Init注解标记的 Service类被认为是一个需要执行操作初始化操作的 Service类, 同时这个 Service类需要实现 IInitService接口。

  @Init(lazy = false) //lazy = false表示禁用懒加载,则该Service会随Application初始化而初始化
  @Service
  public class InitService implements IInitService {  @Override
  public void onInit() {  //do something.
      }
  }

如果初始化组件想要随 Application初始化而初始化,需要将 @Init注解的 lazy赋值为 false,表示禁用懒加载。除了 lazy属性, @Init注解还有 asyncdependencies两个属性。 async属性顾名思义是异步执行, async默认为 false,设置为 true表示该组件初始化会在异步线程执行。 dependencies可以传递一个初始化组件类数组,表示当前组件初始化依赖这个数组中的所有组件。 ServicePool会先初始化数组中的组件再去执行当前组件的初始化。

  @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这篇文章的最后中有实际应用,也可做为示例参考。

组件懒加载机制 & 禁用懒加载

所有初始化操作都随 Application启动执行,一方面会导致 Application非常臃肿,另一方面虽然单个组件初始化时长很短,但 n多个组件初始化时长结合在了一起就会导致启动时间超长。懒加载是 ServicePool的核心思想。所有组件只有在第一次被使用时才会被创建和执行初始化。而不是集中在 Application初始化过程。分散初始化从而减轻 App启动压力。举个????微信分享是很常用的功能,我们以微信分享为例, WXShareManager用来助力微信分享相关操作。

  @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注入对象的时候初始化操作会被执行。

  public class ShareActivity extends AppcompatActivity {  @Service
  private WXShareManager shareManager;//此时会触发WXShareManager的onInit初始化。
    ...  void onClick(View v) {
          shareManager.share(...);
      }
  }

组件热插拔

未完待续....

Activity路由

未完待续....

star下我的GitHub: https://github.com/Meng997998/AndroidJX,给文章点个赞一起学习!


当前文章:程序员不可以错过的Android组件化神器-ServicePool!
本文网址:http://scyanting.com/article/jejiie.html