调用方法、装置和计算机可读存储介质
技术领域
本公开涉及计算机技术领域,特别涉及一种调用方法、装置和计算机可读存储介质。
背景技术
在大型项目开发的过程实践中,主APP(应用)就是一个空壳!有上百个团队来实现功能,每个团队最终会把自己做的模块以SDK(软件开发工具包)的方式集成到主APP。主APP搭载运行这些SDK。
在实际开发中,可以按照正常的开发,引入头文件,实现方法,完成模块间相互通讯。最后打包提供库的时候,必须带上第三方库,因为实际引入了该类库。这样其他团队也使用到相同的第三方库,就会冲突。例如,每个项目组独立开发,都需要网络库、埋点库等常规类库。那么多个团队就包含多个同样功能的类库,集成到主APP,特别是大型项目,几十,上百个团队也是很正常的,诸多的团队在单独开发功能的时候,都会用到一些常见的第三方库,或者中台团队开发的私有库作为其它团队的第三方库。每个团队单独开发功能的时候需要依赖这些库,按照正常的流程开发完毕,最后需把自己团队项目打包,作为SDK提供给主APP。在Pod进行验证,打包的时候就要考虑到库的冲突,多个SDK同时包含了相同的第三方库,集成主APP就会引发重复引用的冲突。Pod为了解决这样的情况,提供了加前缀的指令,即在每个团队进行Pod打包的时候,可以把依赖的相同的第三方库自动加上前缀,这样就暂时解决了重复引用的问题。
发明内容
发明人发现:现有技术中在多个SDK(可以理解为功能模块)集成到主APP的情况下,如果多个SDK引用相同的第三方库,会在第三方库自动加上不同的前缀形成多个第三方库,可以解决引用冲突问题,但是主APP就会包含上百个同样功能的第三方库,体积会非常庞大。
本公开所要解决的一个技术问题是:如何在多个功能模块引用相同的第三方库的情况下,实现功能模块和第三方库的解耦,实现主APP的瘦身,减少数据量。
根据本公开的一些实施例,提供的一种调用方法,包括:路由模块响应于功能模块调用第三方库的方法,获取第三方库的方法的调用相关信息;调用相关信息包括:类名、方法名、参数;路由模块生成类名对应的类;路由模块以方法签名的形式通过生成的类从第三方库中调用方法名对应的方法,并将参数传入,以得到方法的返回值;路由模块将返回值返回给功能模块。
在一些实施例中,路由模块以方法签名的形式通过生成的类从第三方库中调用方法名对应的方法包括:路由模块将类进行实例化,得到实例对象;路由模块对实例对象的公有属性进行赋值;路由模块以方法签名的形式通过实例对象从第三方库中调用方法名对应的方法。
在一些实施例中,参数以指针的形式传入;返回值以指针的形式返回至路由模块。
在一些实施例中,路由模块响应于功能模块调用第三方库的方法,获取第三方库的方法的调用相关信息包括:路由模块响应于功能模块执行过程中识别到切入点,获取第三方库的方法的调用相关信息;其中,功能模块预先配置了切入点。
在一些实施例中,路由模块生成类名对应的类包括:路由模块利用运行时Runtime机制将类名由字符串的类型转换为类的类型,并生成类名对应的类。
在一些实施例中,路由模块将类进行实例化,得到实例对象包括:路由模块利用分配内存Alloc功能对类进行实例化,得到实例对象。
在一些实施例中,路由模块对实例对象的公有属性进行赋值包括:路由模块利用键值编码KVC访问实例对象的公有属性,并对公有属性进行赋值。
在一些实施例中,功能模块,路由模块和第三方库集成到主应用中,功能模块与第三方库不存在直接引用关系。
根据本公开的另一些实施例,提供的一种调用装置,包括:路由模块,用于响应于功能模块调用第三方库的方法,获取第三方库的方法的调用相关信息;调用相关信息包括:类名、方法名、参数;生成类名对应的类;以方法签名的形式通过生成的类从第三方库中调用方法名对应的方法,并将参数传入,以得到方法的返回值;将返回值返回给功能模块。
在一些实施例中,路由模块用于将类进行实例化,得到实例对象;对实例对象的公有属性进行赋值;以方法签名的形式通过实例对象从第三方库中调用方法名对应的方法。
在一些实施例中,参数以指针的形式传入;返回值以指针的形式返回至路由模块。
在一些实施例中,路由模块用于响应于功能模块执行过程中识别到切入点,获取第三方库的方法的调用相关信息;其中,功能模块预先配置了切入点。
在一些实施例中,路由模块用于利用运行时Runtime机制将类名由字符串的类型转换为类的类型,并生成类名对应的类。
在一些实施例中,路由模块用于利用分配内存Alloc功能对类进行实例化,得到实例对象。
在一些实施例中,路由模块用于利用键值编码KVC访问实例对象的公有属性,并对公有属性进行赋值。
在一些实施例中,还包括:功能模块,用于向路由模块传递第三方库的方法的调用相关信息;第三方库,用于响应于路由模块的调用,执行方法名对应的方法。
在一些实施例中,功能模块,路由模块和第三方库集成到主应用中,功能模块与第三方库不存在直接引用关系。
根据本公开的又一些实施例,提供的一种调用装置,包括:处理器;以及耦接至处理器的存储器,用于存储指令,指令被处理器执行时,使处理器执行如前述任意实施例的调用方法。
根据本公开的再一些实施例,提供的一种非瞬时性计算机可读存储介质,其上存储有计算机程序,其中,该程序被处理器执行时实现前述任意实施例调用方法的步骤。
本公开设计了路由模块,路由模块可以接管功能模块对第三方库的调用,响应于功能模块调用第三方库的方法,获取第三方库的方法的调用相关信息,进而根据类名从第三方库获取对应的类,以方法签名的形式调用类中方法名对应的方法,并将参数传入,得到方法的返回值,再由路由模块将返回值返回给功能模块。任何功能模块调用第三方库都可以通过路由模块,在调用的地方,路由模块只需要获取调用相关信息,可以自动获取到该类库的头文件以及调用相应的方法,可以任意调用任何类,任何方法,像调用普通的API那样简单,不存在任何规则限制。在多个不同的功能模块都需要引用同一第三方库的情况下,主APP只需要集成一个该第三方库,任何功能模块都可以通过路由模块实现对该第三方库的调用,实现功能模块和第三方库的完全解耦,减少了对第三方库的维护,减少了主APP的数据量,实现主APP的瘦身。
通过以下参照附图对本公开的示例性实施例的详细描述,本公开的其它特征及其优点将会变得清楚。
附图说明
为了更清楚地说明本公开实施例或现有技术中的技术方案,下面将对实施例或现有技术描述中所需要使用的附图作简单地介绍,显而易见地,下面描述中的附图仅仅是本公开的一些实施例,对于本领域普通技术人员来讲,在不付出创造性劳动的前提下,还可以根据这些附图获得其他的附图。
图1示出本公开的一些实施例的调用方法的流程示意图。
图2示出本公开的另一些实施例的调用方法的流程示意图。
图3示出本公开的一些实施例的调用装置的结构示意图。
图4示出本公开的另一些实施例的调用装置的结构示意图。
图5示出本公开的又一些实施例的调用装置的结构示意图。
具体实施方式
下面将结合本公开实施例中的附图,对本公开实施例中的技术方案进行清楚、完整地描述,显然,所描述的实施例仅仅是本公开一部分实施例,而不是全部的实施例。以下对至少一个示例性实施例的描述实际上仅仅是说明性的,决不作为对本公开及其应用或使用的任何限制。基于本公开中的实施例,本领域普通技术人员在没有做出创造性劳动前提下所获得的所有其他实施例,都属于本公开保护的范围。
本公开提供一种调用方法,下面结合图1进行描述。
图1为本公开调用方法一些实施例的流程图。如图1所示,该实施例的方法包括:步骤S102~S108。
在步骤S102中,路由模块响应于功能模块调用第三方库的方法,获取第三方库的方法的调用相关信息。
调用相关信息例如包括:类名、方法名、参数等。在一些实施例中,路由模块响应于功能模块执行过程中识别到切入点,获取第三方库的方法的调用相关信息;在功能模块中预先配置了切入点。切入点可以实现路由模块的方法与功能模块原本的方法的交换。没有切入点的情况下,功能模块继续执行第三方库的调用,而设置了切入点之后,在执行到切入点的情况下,转换为由路由模块执行路由模块中封装的方法。上述方法采用了AOP(AspectOriented Programming,面向切面编程)的方法。第三方库允许多个不同的功能模块通过路由模块进行调用。功能模块,路由模块和第三方库集成到主应用中,功能模块与第三方库不存在直接引用关系。
在步骤S104中,路由模块生成类名对应的类。
在一些实施例中,第三方库的方法的调用相关信息可以通过字符串的形式由功能模块传递给路由模块。路由模块利用运行时Runtime机制将类名由字符串的类型转换为类的类型,并生成类名对应的类。生成的类与第三方库的类采用相同的类名,即调用相关信息中包含的类名。例如,在iOS系统中,可以通过NSClassFromString的方法初始化类,该方法中传入的参数className是字符串形式的类名,返回值是类的初始化实例。通过Runtime的机制,把第三方库的类名以字符串的传给路由模块,由路由模块通过class转换来获取该类。在调用的地方,不在引入该类库的头文件,做到完全解耦合。
在步骤S106中,路由模块以方法签名的形式通过生成的类从第三方库中调用方法名对应的方法,并将参数传入,以得到方法的返回值。
在一些实施例中,路由模块将类进行实例化,得到实例对象;路由模块对实例对象的公有属性进行赋值;路由模块以方法签名的形式通过实例对象从第三方库中调用方法名对应的方法。不同的第三方库的实现不同,有一些第三方库可以没有实例化或对公有属性赋值的过程。
对类进行实例化,例如,路由模块通过类名获取到对应的类,经过alloc进行初始化,得到实例对象。
对公有属性赋值,例如,路由模块利用键值编码(KVC)访问实例对象的公有属性,并对公有属性进行赋值。例如,可以以属性字典组合的形式传入属性字符串和对应的值,key表示属性名字符串,value表示该属性需要被赋予的值。根据属性字典组合对需要被赋值的对象进行赋值。
例如,在iOS系统,把实例对象的需要赋值的属性通过key-value的方式,组合到字典NSDictionary,作为路由的一个参数传入。在处理过程中通过遍历元素,通过调用enumerateKeysAndObjectsWithOptions:NSEnumerationReverse usingBlock:方法取出,再使用系统的setValue:forKey:方法进行属性实际设置。
在一些实施例中,调用方法时参数以指针的形式传入;返回值以指针的形式返回至路由模块。例如,在iOS开发中,最常用的数据类型就是继承NSObject类型的参数,经常出现参数为基本数据类型,枚举,或者结构体的形式入参。在参数有种形式的情况下,对于NSInvocation的兼容机需要考虑很多,为了让路由模块可以任意调用方法,不考虑参数的类型,采用指针的形式指向的一块内存空间。把所有的参数,转换为其指针,作为指针入参。
以指针的形式传入参数,不再以常规的固定类型参数入参,类型固定有诸多限制。只需要知道应该传入的什么类型是什么,声明的时候定义为该类型的变量,入参的时候取地址进行入参,也是本路由的核心设计实现,也正是iOS的系统特性-动态运行,动态加载,动态绑定才能实现。例如,iOS系统中,地址参数接收以后,对参数使用,使用方法签名把方法名和参数结合起来,实现调用方法。
NSUInteger bufferSize=0;
NSGetSizeAndAlignment([obj objCType],&bufferSize,NULL);
void*buffer=malloc(bufferSize);
[obj getValue:&buffer];
[invocation setArgument:buffer atIndex:(2+idx)];
不同于普通参数的使用,调用方法getValue的时候传入的为指针的地址。
通过方法签名的形式调用方法,例如,iOS系统的方法签名封装了方法调用对象、方法选择器、参数、返回值等。任何iOS的方法均可以用方法签名(NSInvocation)的形式调用。例如,可以通过NSSelectorFromString的方法实现根据方法名的字符串查找相应的方法,例如,SEL methodSelect=NSSelectorFromString(methodpString),methodSelect为变量名,methodpString为方法名。可以通过NSMethodSignatur的方法获取方法的签名,例如NSMethodSignature*singnature=[instansObject methodSignatureForSelector:,instansObject表示要获取的对象。可以通过NSInvocation的方法根据方法签名调用方法。例如,通过NSInvocation*invocation=[NSInvocationinvocationWithMethodSignature:singnature],根据方法签名初始化NSInvocation对象,利用invocation.target对NSInvocation对象设置方法调用者,利用invocation.selectort对NSInvocation对象设置方法选择器,利用nvocationsetArgument:对NSInvocation对象设置参数,利用invocation invoke执行NSInvocation对象中的指定方法,并传递指定参数。
在步骤S108中,路由模块将返回值返回给功能模块。
上述实施例的方法设计了路由模块,路由模块可以接管功能模块对第三方库的调用,响应于功能模块调用第三方库的方法,获取第三方库的方法的调用相关信息,进而根据类名从第三方库获取对应的类,以方法签名的形式调用类中方法名对应的方法,并将参数传入,得到方法的返回值,再由路由模块将返回值返回给功能模块。任何功能模块调用第三方库都可以通过路由模块,在调用的地方,路由模块只需要获取调用相关信息,可以自动获取到该类库的头文件以及调用相应的方法,可以任意调用任何类,任何方法,像调用普通的API那样简单,不存在任何规则限制。在多个不同的功能模块都需要引用同一第三方库的情况下,主APP只需要集成一个该第三方库,任何功能模块都可以通过路由模块实现对该第三方库的调用,实现功能模块和第三方库的完全解耦,减少了对第三方库的维护,减少了主APP的数据量,实现主APP的瘦身。
下面结合图2描述本公开调用方法的另一些实施例。
图2为本公开调用方法另一些实施例的流程图。如图2所示,该实施例的方法包括:步骤S202~S212。
在步骤S202中,路由模块响应于功能模块调用第三方库的方法,获取第三方库的方法的调用相关信息。
调用相关信息例如包括:类名、方法名、参数。
在步骤S204中,路由模块利用Runtime机制生成类名对应的类。
在步骤S206中,路由模块将类进行实例化,得到实例对象。
在步骤S208中,路由模块利用键值编码对实例对象的公有属性进行赋值。
在步骤S210中,路由模块以方法签名的形式通过实例对象从第三方库中调用方法名对应的方法,并将参数传入,以得到方法的返回值。
在步骤S212中,路由模块将返回值返回给功能模块,实现功能模块对第三方库的调用。
本方案可以用于iOS框架中,通过指针参数、KVC、AOP、方法签名等技术,解决功能模块和第三方库的耦合问题,实现类、实例方法的任意调用。使用指针入参,支持基本数据类型、OC对象类型、结构体、block块、代理等。通过KVC来实现属性的动态赋值操作,实现大型APP任意模块之间的解耦。尤其是解决依赖pod管理开发的大型组件相互依赖,和不同SDK底层依赖相同第三方库产生的冲突问题,使得各个SDK完全解耦。在同一个项目上,相同功能的第三方库只存在一份,而不是通过加前缀来实现库的冲突。
对于iOS系统,由于其运行时的特性,对变量,属性等是动态加载,动态绑定的,所以可以预先把参数,属性等声明成id类型或者任意与实际底层库的方法参数能对接的数据类型,并且把声明的变量取地址,把地址作为实际的参数进行传入。然后在方法签名实现具体方法的时候,把指针地址转成对应的数据类型调用底层的实际方法。实现任意参数跨度传递,解决参数类型多样性的难题。
本方案的路由模块封装了字符串类名获取类的方法,目的是得到欲调用的类。然后路由封装了通过类获取实例的方法,得到类的实例。其次,路由模块对类方法进行了封装,可以直接调用类方法,最后,路由对实例方法进行了封装,可以直接调用实例方法。对于在调用实例的之前,需要给实例属性赋值的,路由模块以key-value的形式封装了属性赋值的方法。
如果将现有的URL Scheme()作为一种路由模式,这种方式需要事先定义好调用规则,定义好入参,出参数规则,根据不同的模块来定义跳转的URL Scheme。主APP来维护一个单例,单例会维护一个数组来储存对应的定义好的规则URL Scheme和对应的参数。在实际业务调用中,会进行规则的匹配,然后根据匹配到的URL Scheme,再关联到跳转的参数,然后根据参数的规则跳转对应的控制器或者模块。这种方式,由于规则性强,是针对解决某一个APP而出现的解决方案,规则一旦既定,那么必须完全匹配这套准则,通用性很差。如果行的APP接入,接入成本太高,接入方需要把已有项目的模块API全部按照规则来,才能适配,所以移植性比较差。每个组件或者每个类都需要初始化,内存里需要保存一份HashMap,组件URL过多就会有内存问题。过多的url,索引匹配复杂度会提升,会有相应的性能问题。参数并非一致,而是一个灵活的字典,需要有地方可参考,有规则可依附。开发的时候,就需要定制一套完整的方案,规则,比如以什么字符串作为标记,需要遵循怎样的调用。后台需要怎样的一套维护准则,有新的模块或者新功能,项目要及时维护更新,把新的URL集成等,需要专门的团队来维护。而基于本公开的前述实施例可以看出本公开的方案可以解决上述问题,不需要制定规则,可以实现任意类、任意方法等的调用。
本公开还提供一种调用装置,下面结合图3进行描述。
图3为本公开调用装置的一些实施例的结构图。如图3所示,该实施例的装置30包括:路由模块310;以及功能模块320,第三方库330。
路由模块310用于响应于功能模块调用第三方库的方法,获取第三方库的方法的调用相关信息;调用相关信息包括:类名、方法名、参数;生成类名对应的类;以方法签名的形式通过生成的类从第三方库中调用方法名对应的方法,并将参数传入,以得到方法的返回值;将返回值返回给功能模块。
在一些实施例中,路由模块310用于将类进行实例化,得到实例对象;对实例对象的公有属性进行赋值;以方法签名的形式通过实例对象从第三方库中调用方法名对应的方法。
在一些实施例中,参数以指针的形式传入;返回值以指针的形式返回至路由模块310。
在一些实施例中,路由模块310用于响应于功能模块执行过程中识别到切入点,获取第三方库的方法的调用相关信息;其中,功能模块320预先配置了切入点。
在一些实施例中,路由模块310用于利用运行时Runtime机制将类名由字符串的类型转换为类的类型,并生成类名对应的类。
在一些实施例中,路由模块310用于利用分配内存Alloc功能对类进行实例化,得到实例对象。
在一些实施例中,路由模块310用于利用键值编码KVC访问实例对象的公有属性,并对公有属性进行赋值。
在一些实施例中,功能模块320用于向路由模块传递第三方库的方法的调用相关信息;第三方库330用于响应于路由模块310的调用,执行方法名对应的方法。功能模块320预先配置了切入点,用于在执行过程中识别到切入点,向路由模块传递第三方库的方法的调用相关信息。
在一些实施例中,路由模块310,功能模块320和第三方库330集成到主应用中,功能模块320与第三方库330不存在直接引用关系。
本公开的实施例中的调用装置可各由各种计算设备或计算机系统来实现,下面结合图4以及图5进行描述。
图4为本公开调用装置的一些实施例的结构图。如图4所示,该实施例的装置40包括:存储器410以及耦接至该存储器410的处理器420,处理器420被配置为基于存储在存储器410中的指令,执行本公开中任意一些实施例中的调用方法。
其中,存储器410例如可以包括系统存储器、固定非易失性存储介质等。系统存储器例如存储有操作系统、应用程序、引导装载程序(Boot Loader)、数据库以及其他程序等。
图5为本公开调用装置的另一些实施例的结构图。如图5所示,该实施例的装置50包括:存储器510以及处理器520,分别与存储器410以及处理器420类似。还可以包括输入输出接口530、网络接口540、存储接口550等。这些接口530,540,550以及存储器510和处理器520之间例如可以通过总线560连接。其中,输入输出接口530为显示器、鼠标、键盘、触摸屏等输入输出设备提供连接接口。网络接口540为各种联网设备提供连接接口,例如可以连接到数据库服务器或者云端存储服务器等。存储接口550为SD卡、U盘等外置存储设备提供连接接口。
本领域内的技术人员应当明白,本公开的实施例可提供为方法、系统、或计算机程序产品。因此,本公开可采用完全硬件实施例、完全软件实施例、或结合软件和硬件方面的实施例的形式。而且,本公开可采用在一个或多个其中包含有计算机可用程序代码的计算机可用非瞬时性存储介质(包括但不限于磁盘存储器、CD-ROM、光学存储器等)上实施的计算机程序产品的形式。
本公开是参照根据本公开实施例的方法、设备(系统)、和计算机程序产品的流程图和/或方框图来描述的。应理解为可由计算机程序指令实现流程图和/或方框图中的每一流程和/或方框、以及流程图和/或方框图中的流程和/或方框的结合。可提供这些计算机程序指令到通用计算机、专用计算机、嵌入式处理机或其他可编程数据处理设备的处理器以产生一个机器,使得通过计算机或其他可编程数据处理设备的处理器执行的指令产生用于实现在流程图一个流程或多个流程和/或方框图一个方框或多个方框中指定的功能的装置。
这些计算机程序指令也可存储在能引导计算机或其他可编程数据处理设备以特定方式工作的计算机可读存储器中,使得存储在该计算机可读存储器中的指令产生包括指令装置的制造品,该指令装置实现在流程图一个流程或多个流程和/或方框图一个方框或多个方框中指定的功能。
这些计算机程序指令也可装载到计算机或其他可编程数据处理设备上,使得在计算机或其他可编程设备上执行一系列操作步骤以产生计算机实现的处理,从而在计算机或其他可编程设备上执行的指令提供用于实现在流程图一个流程或多个流程和/或方框图一个方框或多个方框中指定的功能的步骤。
以上所述仅为本公开的较佳实施例,并不用以限制本公开,凡在本公开的精神和原则之内,所作的任何修改、等同替换、改进等,均应包含在本公开的保护范围之内。