程序员不可以错过的Android组件化神器-ServicePool!
组件化开发过程中,随着组件越来越多,组件的之前的交互就会变得非常的复杂,此时组件间通信变得尤其的重要,ServicePool
就是为组件化而生,用最简单的方式进行组件间通信。
使用依赖注入,按需灵活注入组件。同时支持组件热插拔,达到组件即插即用的效果。可配置组件生命周期,做到组件按需创建和及时回收,充分利用懒加载的思想,有效解决组件初始化耗时导致的app
启动速度问题。
ServicePool
包含有Activity
路由, 组件路由等等最常用的组件化能力。除此之外,组件化开发过程中有没有遇到过想使用某个已有的类,比如一个工具类的时候,发现这个工具类在当前类的上层,无法直接依赖和引用,而修改这个工具类的层级又会牵一发而动全身的问题?有没有想要一个差异响应的能力,在不同的组件中或者环境下,有着不同的响应方式?有没有想要一个自适应场景的能力,自动适应当前环境(比如Java
还是Android
环境,比如Debug
环境还是Release
环境等等),从而使用最合适的功能。又有没有想过如何让组件做到像USB接口一样插上就能直接使用,拔掉也不影响主体功能的即插即用的效果。等等...。下面就来具体介绍一下这个组件化神器——ServicePool
!
如上图所示:
组件A
,B
是两个互不依赖的组件,A
,B
不能直接通信组件A
,B
分别通过AService
,BService
对外提供服务组件A
,B
的接口协议存放在组件服务池pool
, 分别是接口IA, IB当组件B需要组件A的服务时,组件B使用IA接口向ServicePool
申请, 由ServicePool
创建并返回aService
给组件B, 此时组件b
可以使用aService
的服务了同理, 组件A
使用IB
向ServicePool
申请bService
aService
,bService
由ServicePool
创建和管理所有Service
对象的优先级生命周期可以通过@Service
注解配置/***服务池pool中**IA.java*/publicinterfaceIA{voidaName();}/***服务池pool**IB.java*/publicinterfaceIB{voidbName();}
/***组件A**AService.java*/@ServicepublicclassAServiceimplementsIA{@OverridepublicStringaName(){return"AService";}}
/***组件B**BService.java*/@ServicepublicclassBServiceimplementsIB{@OverridepublicStringbName(){return"BService";}}
组件A中执行:IBb=ServicePool.getService(IB.class);System.out.println("I'mAService,Icanget"+b.bName());输出:I'mAService,IcangetBService组件B中执行:IAa=ServicePool.getService(IA.class);System.out.println("I'mBService,Icanget"+a.aName());输出:I'mBService,IcangetAService依赖注入(DI)
由于所有示例涉及到依赖注入,这里提前对ServicePool
的依赖注入做个说明。和其他注入框架不同,ServicePool
的注入方式很简单,只有一种注入方式就是直接通过类注入。
@ServicepublicclassAImplimplementsIA{@OverridepublicStringaName(){return"AImpl"}}
ServicePool
就是一个注入容器。最后通过ServicePool
.getService(IA.class)
方法注入对象, 也可以通过@Service
标记成员变量的方式注入,这两个方法等价。
publicclassMainActivityextendsAppcompatActivity{/***等价于*IA=ServicePool.getService(IA.class);*/@ServiceprivateIAa;@OverridepublicvoidonCreate(BundlesavedInstanceState){System.out.println(a.getName());//输出AService}}
ServicePool
注入对象时,会根据Service
配置的生命周期类型(scope)
和优先级来决定当前是创建还是直接返回缓存对象。
如果IA有多个实现,如上图所示,ServicePool
会比较每个实现优先级,来决定最
终返回IA的哪个实现
@Service
注解标记一个实现类时候可以通过参数priority指定这个实现类的优先级优先级值越大优先级越高,ServicePool
默认会返回优先级最高的实现类对象如果多个实现类优先级相同,那么返回会有不确定性也可以直接指定具体使用哪个实现类,如ServicePool
.getService(AService1.class)
将会返回一个AService1
对象/***服务池pool中**IPriorityService.java*/publicinterfaceIPriorityService{intgetPriority();}
/***组件A中**PriorityService1.java*PriorityService2.java*/@Service(priority=1)publicclassPriorityService1implementsIPriorityService{@OverridepublicintgetPriority(){return1;}}@Service(priority=2)publicclassPriorityService2implementsIPriorityService{@OverridepublicintgetPriority(){return2;}}
组件B中执行:IPriorityServicepriorityService=ServicePool.getService(IPriorityService.class);System.out.println("priorityis"+priorityService.getPriority());priorityService=ServicePool.getService(PriorityService1.class);System.out.println("priorityis"+priorityService.getPriority());priorityService=ServicePool.getService(PriorityService2.class);System.out.println("priorityis"+priorityService.getPriority());输出:priorityis2priorityis1priorityis2
典型应用场景
Java Library
组件和Android Library
组件使用不同的服务, 如classloader
等等。debug
环境,release
环境或者不同的productFlavor
使用不同的服务, 如logger
,Mock
等等不同的业务场景使用不同的服务给服务对象指定生命周期每个由ServicePool
创建的service
对象都有各自生命周期,service
对象的生命周期由ServicePool
管理, 并由@Service
注解配置生命周期类型。
Service
有once
,temp
,global
三种生命周期类型.指定Service
的生命周期为once
,@Service(scope=IService.Scope.once)
,每次ServicePool.getService()
都会创建一个新的对象,对象使用后随gc
自动被回收,scope
默认为once
指定Service
的生命周期为temp
,@Service(scope=IService.Scope.temp)
,Service
由WeakReference
缓存,只适用无状态服务。指定Service
的生命周期为global
,@Service(scope=IService.Scope.global)
,每次ServicePool.getService()
拿到的都是同一个对象,App
运行期间不会被回收组件A中/****OnceService.java*/@Service(scope=IService.Scope.once)publicclassOnceServiceimplementsLifecycleService{}/****TempService.java*/@Service(scope=IService.Scope.temp)publicclassTempServiceimplementsLifecycleService{}/****GlobalService.java*/@Service(scope=IService.Scope.global)publicclassGlobalServiceimplementsLifecycleService{}
组件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*/publicinterfaceIPathService{StringpathServiceName();}
/***组件A中**PathService*/@Service(path="pathService")publicclassPathServiceimplementsIPathService{@OverridepublicStringpathServiceName(){return"PathService";}}
IPathService
是任意定义的接口,它可以有一个或多个实现类,只要在实现类上加@Service
注解并指定path
属性。我们就可以通过ServicePool.getService(path)
来找到或者创建他的实现类对象。
组件B中执行:IPathServicepathService=ServicePool.getService("pathService");System.out.println(pathService.pathServiceName());输出:PathService典型应用场景:activity
路由混合开发中,可以通过path
将桥接方法分发到对应执行器组件初始化
app
开发过程中,肯定少不了对组件进行初始化,无论是内部组件还是引用外部库,很多都需要执行初始化操作。常规的方式是所有初始化操作都是放到Application
的onCreate()/onAttachBaseContext()
方法中执行。组件有很多而Application
只有1
个, 如何让每个组件都可以拥有它自己的初始化类呢?ServciePool
中有一个@Init
注解,任何被@Init
注解标记的Service
类被认为是一个需要执行操作初始化操作的Service
类, 同时这个Service
类需要实现IInitService
接口。
@Init(lazy=false)//lazy=false表示禁用懒加载,则该Service会随Application初始化而初始化@ServicepublicclassInitServiceimplementsIInitService{@OverridepublicvoidonInit(){//dosomething.}}
如果初始化组件想要随Application
初始化而初始化,需要将@Init
注解的lazy
赋值为false
,表示禁用懒加载。除了lazy
属性,@Init
注解还有async
,dependencies
两个属性。async
属性顾名思义是异步执行,async
默认为false
,设置为true
表示该组件初始化会在异步线程执行。dependencies
可以传递一个初始化组件类数组,表示当前组件初始化依赖这个数组中的所有组件。ServicePool
会先初始化数组中的组件再去执行当前组件的初始化。
@Init@ServicepublicclassInitService1implementsIInitService{@OverridepublicvoidonInit(){System.out.println("Service1Inited!!!");}}@Init@ServicepublicclassInitService2implementsIInitService{@OverridepublicvoidonInit(){System.out.println("Service2Inited!!!");}}@Init(lazy=false,dependencies=[InitService1.class,InitService2.class])@ServicepublicclassInitService3implementsIInitService{@OverridepublicvoidonInit(){System.out.println("Service3Inited!!!");}}
ServicePool
的初始化在
https://juejin.im/post/5e1ef261f265da3e0535f10a这篇文章的最后中有实际应用,也可做为示例参考。
所有初始化操作都随Application
启动执行,一方面会导致Application
非常臃肿,另一方面虽然单个组件初始化时长很短,但n
多个组件初始化时长结合在了一起就会导致启动时间超长。懒加载是ServicePool
的核心思想。所有组件只有在第一次被使用时才会被创建和执行初始化。而不是集中在Application
初始化过程。分散初始化从而减轻App
启动压力。举个????微信分享是很常用的功能,我们以微信分享为例,WXShareManager
用来助力微信分享相关操作。
@Init@ServicepublicclassWXShareManagerimplementIInitService{publicstaticfinalStringappId="wx499fa9b1ba4a93db";publicstaticfinalStringuserName="gh_6619a14a139d";@OverridepublicvoidonInit(){IWXAPIwxApi=WXAPIFactory.createWXAPI(mContext,null);wxApi.registerApp(appId);}publicvoidshare(...){//dowxshare.}}
shareManager
注入对象的时候初始化操作会被执行。
publicclassShareActivityextendsAppcompatActivity{@ServiceprivateWXShareManagershareManager;//此时会触发WXShareManager的onInit初始化。...voidonClick(Viewv){shareManager.share(...);}}组件热插拔
未完待续....
Activity路由未完待续....
star下我的GitHub:https://github.com/Meng997998/AndroidJX,给文章点个赞一起学习!
声明:本站所有文章资源内容,如无特殊说明或标注,均为采集网络资源。如若本站内容侵犯了原著者的合法权益,可联系本站删除。