HarmonyOS NEXT智能终端应用开发 课件 第11章 多模块应用开发_第1页
HarmonyOS NEXT智能终端应用开发 课件 第11章 多模块应用开发_第2页
HarmonyOS NEXT智能终端应用开发 课件 第11章 多模块应用开发_第3页
HarmonyOS NEXT智能终端应用开发 课件 第11章 多模块应用开发_第4页
HarmonyOS NEXT智能终端应用开发 课件 第11章 多模块应用开发_第5页
已阅读5页,还剩43页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

第11章多模块应用开发一个应用通常包含多种功能,将不同的功能特性按模块(也就是Module)来划分和管理是一种良好的设计开发方式。多模块开发具有如下优势:其一,每个模块可以包含源代码、资源文件、第三方库、配置文件等,可以独立编译,实现特定的功能;其二,每个模块可以安排不同的人员进行开发,这种模块化、松耦合的应用管理方式有利于应用的开发、维护与扩展,同时也为团队合作提供可能。本节对多模块开发进行介绍。目录11.1应用程序模块类型和应用程序包结构11.2创建多模块应用程序11.3模块之间的程序/资源引用11.4案例:多模块程序资源访问11.5练习:多模块引用案例再现11.1应用程序模块类型和应用程序包结构鸿蒙支持多种类型的模块类型,不同的模块类型在开发时和打包到应用程序包中时,呈现的结果也不尽相同。11.1.1应用程序模块类型鸿蒙应用程序可以包含四种类型的模块,它们是:entry类型的Module、feature类型的Module、静态共享库、动态共享库。1、entry类型的Module应用的主模块,包含应用的入口界面、入口图标和主功能特性,编译后生成entry类型的HAP(HarmonyAbilityPackage,后缀名为.hap)。每一个应用程序分发到同一类型的设备上的应用程序包,只能包含唯一一个entry类型的HAP,也可以不包含。HAP包可以独立安装和运行,是应用安装的基本单位。一个应用程序可以包含一个或多个HAP包。2、feature类型的Module应用的动态特性模块,编译后生成feature类型的HAP。一个应用中可以包含一个或多个feature类型的HAP,也可以不包含。feature模块与entry模块非常类似,只是在feature模块中不包含入口UIAbility。3、静态共享库也称为StaticLibrary,用于实现代码和资源的共享,其中主要存放其他模块需要公用的代码和资源,例如,某个在多个其他模块中需要调用的方法等。同一个Library类型的Module可以被其他的Module多次引用,合理地使用该类型的Module,能够降低开发和维护成本。静态共享库编译后生成HAR包,即静态共享包HAR(HarmonyArchive,后缀名为.har)。4、动态共享库也称为SharedLibrary,用于实现代码和资源的共享,其中主要存放其他模块需要公用的代码和资源,编译后生成一个以.hsp为后缀的文件,即动态共享包HSP(HarmonySharedPackage)。动态共享库与静态共享库的区别在于:当多包同时依赖同一个动态共享库时,使用HSP替代HAR,可以避免HAR造成的多包间代码和资源的重复拷贝,从而减小应用包大小。简单来说,动态共享库与静态共享库的区别相当于操作系统中的静态库与动态连接库的关系。如上所述的四种模块类型,开发者可以根据具体的应用需求,选择相应类型的包进行开发。下表对HAP包类型、HAR包类型、HSP包类型可以包含的程序元素进行了对比说明。序号规格HAPHARHSP1支持在配置文件中声明UIAbility组件√√√2支持在配置文件中声明ExtensionAbility组件√×√3支持在配置文件中声明pages页面√×√4支持包含资源文件√√√5支持依赖其他HAR文件√√√6支持依赖其他HSP文件√√√7支持在设备上独立安装运行√××11.1.2应用程序包结构应用程序包结构包括开发态包结构和编译态包结构。第一章已经介绍了应用程在开发态的包结构,本节对应用程序的编译态结构进行介绍。不同类型的Module编译后会生成对应的HAP、HAR、HSP等文件。现在假设已经创建了一个应用程序,其中包含四个模块,则这个程序工程的开发态视图与编译态视图的对照关系如图。从图可以看出,这个程序工程包括4个模块,分别是:一个名称为entry的entry模块、一个名称为feature的feature模块、一个名称为libraryA的动态共享库、一个名称为libraryB的静态共享库。经过编译打包后,entry模块、feature模块、动态共享库都将分别打包成相应的HAP文件或者HSP文件,对于静态共享库,则将其HAR包编译打包到其依赖包中。同时注意到,整个应用程序将打包并生成一个后缀为.app的应用程序包。11.2创建多模块应用程序当使用DevEco创建应用程序时,默认会创建一个只包含entry模块的应用程序。在创建了应用程序后,可以根据需要创建其他类型的模块。为了介绍如何创建多模块应用,先创建一个名称为ch1101的程序工序工程。观察ch1101工程可以发现,工程中包含一个名称为entry的entry模块:本章之前所有章节的所有例子程序及案例程序都只包含名称为entry的entry模块。现在在ch1101工程新建多个其他类型的模块:一个名称为mf的feature模块、一个名称为ms的静态共享库、一个名称为md的动态共享库。需要一个一个地创建这些模块。为了在ch1101工程新建模块,如图所示,首先鼠标右击工程名称,在弹出地菜单中选择New,并进一步选择Module,如图所示。在上图的界面中分别选择EmptyAbility、StaticLibrary、SharedLibrary,为工程ch1101新建三个模块,新建完成后,工程的界面如图所示。应用程序除了只能包含一个entry模块的限制外,可以根据需要包含0个或者多个feature模块、静态共享库、动态共享库。开发者可以根据模块的功能和要求,将模块委托给相关人员开发,从而实现团队的分工和协作,同时开发者可以根据表11-1的说明,在模块中存放应用程序代码、资源等程序内容。11.3模块之间的程序/资源引用在多模块应用程序中,不同的模块会包含不同的程序代码、资源,模块之间会存在对这些分布于不同模块的程序代码、资源的引用。本节对模块之间的程序代码及资源的引用进行介绍。11.3.1跨模块资源引用在一个模块中定义的资源可以被其他模块引用。依托上一节的例子,假设在md模块中的string.json中定义了如下字符串资源:{"string":[{"name":"shared_desc","value":"stringfromshared"},{"name":"shared_other","value":"anotherstringfromshared"}]}现在需要在entry模块的Index.ets页面访问这两个字符串资源:在Index页面的文本框中显示名称为shared_desc字符串资源的值;点击Index页面上的按钮,在按钮上显示名称为other字符串的值。模块之间的引用相互引用的方法是类似的,下面以entry模块引用md模块的资源进行介绍。为了在entry模块引用md模块的资源,需要在entry模块的oh-package.json5文件中进行配置,entry模块增加引用md资源配置后的代码如下:{"name":"entry","version":"1.0.0","description":"Pleasedescribethebasicinformation.","main":"","author":"","license":"","dependencies":{"md":"file:../md"}}在dependencies标签下的语句:

"md":"file:../md"就表示entry模块需要引用md模块,其中,“md”指定被引用的模块名,“file:../md”指定被引用的模块的路径:这个路径指明是被引用的模块相对于引用模块的相对路径。之后,在DevEco的Terminal控制台执行命令ohpminstall,如图。现在,修改Index.ets文件,在其中显示一个文本框、一个按钮,并分别引用md模块的字符串资源。修改后的代码如下:import{application}from'@kit.AbilityKit';

@Entry@ComponentstructIndex{@Statemessage:string='[md].string.shared_desc';@Statetext:string='点击见证奇迹';

build(){Column(){Text($r(this.message)).width('100%').height(50).margin(10).fontSize(25).textAlign(TextAlign.Center).border({width:1,radius:4})Button(this.text).width('100%').height(50).margin(10).fontSize(25).onClick(async()=>{letmc=awaitapplication.createModuleContext(getContext(),"md");this.text=mc.resourceManager.getStringByNameSync("shared_other");})}.height('100%').width('100%')}}11.3.2跨模块页面组件引用不同模块之间的页面组件也是可以相互引用的。现在假设entry模块要引用ms模块的MainPage.ets中的页面组件MainPage。为此,与上一节entry模块要引用md模块中的资源类似,需要在entry模块的oh-packages.json5文件添加对ms模块的依赖。修改后的entry模块的oh-packages.json5文件内容如下:{"name":"entry","version":"1.0.0","description":"Pleasedescribethebasicinformation.","main":"","author":"","license":"","dependencies":{"md":"file:../md","ms":"file:../ms"}}添加了对ms模块的依赖后,可以在DevEco的Terminal控制台执行命令ohpminstall,具体可参考上一小节介绍,或者,直接点击DevEco的顶部出现的“Syncnow”来完成依赖的构建,如图。为了能够被其他模块使用,被依赖模块中的所有需要被共享的页面组件需要使用export关键字导出。例如,由于ms模块的MainPage.ets页面的MainPage组件需要被entry模块使用,因此,MainPage组件需要使用export导出。完成的MainPage.ets文件内容如下:@ComponentexportstructMainPage{@Statemessage:string='HelloWorld';

build(){Row(){Column(){Text(this.message).fontSize($r('app.float.page_text_font_size')).fontWeight(FontWeight.Bold).onClick(()=>{this.message='Welcome';})}.width('100%')}.height(70)}}由于在entry模块的Index.ets页面中要使用这个组件,因此,需要在entry模块的Index.ets文件中导入这个组件。修改后的entry模块的Index.ets如下:import{application}from'@kit.AbilityKit';import{MainPage}from'ms'

@Entry@ComponentstructIndex{@Statemessage:string='[md].string.shared_desc';@Statetext:string='点击见证奇迹';

build(){Column(){Text($r(this.message)).width('100%').height(50).margin(10).fontSize(25).textAlign(TextAlign.Center).border({width:1,radius:4})Button(this.text).width('100%').height(50).margin(10).fontSize(25).onClick(async()=>{letmc=awaitapplication.createModuleContext(getContext(),"md");this.text=mc.resourceManager.getStringByNameSync("shared_other");})Divider().width('100%').height(10)MainPage()}.height('100%').width('100%')}}11.3.3跨模块方法/类/接口引用跨模块方法/类/接口引用的方式和过程与上一小节“跨模块页面组件引用”类似。第一步,首先在引用模块的oh-package.json5文件中配置对被引用模块的依赖;第二步,对被引用模块中允许引用的方法/类/接口使用export关键字导出;第三步,在引用模块中导入到引用的方法/类/接口:此处需要明确从哪个模块的哪个文件导入方法/类/接口。下面举个例子说明如何跨模块方法/类/接口,只以引用方法为例说明。假设md模块要引用ms模块的add()方法一完成两个数的“魔术”加法。在md模块的oh-package.json5文件添加对ms模块的依赖:{"name":"md","version":"1.0.0","description":"Pleasedescribethebasicinformation.","main":"Index.ets","author":"","license":"Apache-2.0","packageType":"InterfaceHar","dependencies":{"ms":"file:../ms"}}由于add()方法是一个完成具体功能方法,为了逻辑清晰性,将其放置在ms模块的源代码目录ets下的一个utils子目录下,为此,在ets下新建utils子目录,并在其中新建名称为functions.ets文件。functions.ets文件内容如下:exportfunctionadd(a:number,b:number):number{letc=(a+b)%100;returnc;}假设现在需要在md模块的Index.ets页面中引用这个方法,则需要首先在Index.ets中导入这个方法。修改后的Index.ets文件如下:import{add}from'ms/src/main/ets/utils/functions'

@Entry@ComponentstructIndex{@Statemessage:string='HelloWorld';

build(){Row(){Column(){Text(this.message).fontSize($r('app.float.page_text_font_size')).fontWeight(FontWeight.Bold).onClick(()=>{lett=add(100,209);this.message='Welcome:'+t;})}.width('100%')}.height('100%')}}11.3.4跨模块UIAbility引用跨模块UIAbility引用,本质上就是通过Want启动(拉起)位于其他模块的UIAblity,因此,本质上与第5章第3节介绍的Want是一致的:只是在第5章,使用Want拉起的是同一个模块中的UIAbility,在这里,将使用Want拉起位于其他模块的UIAblity。下面举一个例子演示如何跨模块拉起UIAbility。在entry模块的Index页面中,点击按钮,拉起mf模块的MfAbility。由于是通过Want拉起UIAbility,因此,不需要在entry模块中配置对mf模块的依赖。修改entry模块的Index.ets文件为如下内容:import{application,common,Want}from'@kit.AbilityKit';import{MainPage}from'ms'import{hilog}from'@kit.PerformanceAnalysisKit';import{BusinessError}from'@kit.BasicServicesKit';

@Entry@ComponentstructIndex{@Statemessage:string='[md].string.shared_desc';@Statetext:string='点击见证奇迹';

build(){Column(){Text($r(this.message)).width('100%').height(50).margin(10).fontSize(25).textAlign(TextAlign.Center).border({width:1,radius:4})Button(this.text).width('100%').height(50).margin(10).fontSize(25).onClick(async()=>{letmc=awaitapplication.createModuleContext(getContext(),"md");this.text=mc.resourceManager.getStringByNameSync("shared_other");})Divider().width('100%').height(10)MainPage()Divider().width('100%').height(10)Button("跨模块拉起").width('100%').height(50).margin(10).onClick(()=>{//通过startAbility接口显式启动其他UIAbility,推荐使用openLink接口。letwant:Want={bundleName:"com.example.ch1101",moduleName:"mf",abilityName:"MfAbility"};try{letcontext=this.getUIContext().getHostContext()ascommon.UIAbilityContext;context.startAbility(want).then(()=>{(0x0000,'ttt','startAbilitysuccess.');}).catch((err:BusinessError)=>{console.log(`startAbilityfailed.Code:${err.code},message:${err.message}`);})}catch(paramError){console.log(`Failed.Code:${paramError.code},message:${paramError.message}`);}})}.height('100%').width('100%')}}由于UIAbility分布在不同的模块中,因此,在可以运行这个程序之前,需要确保entry模块、mf模块、md模块均已经正确部署。为此,在DevEco中,点击“entry”右边的下三角,选择“EditConfiguration”,如图。此时,将显示如图。确保方框3显示的模块都已经打勾,然后点击“OK”按钮完成配置。11.4案例:多模块程序资源访问上一节对多模块的代码及资源的引用做了介绍,本节再通过一个完整的例子强化对多模块开发技术的应用。11.4.1案例目标编写一个应用程序,该程序包括一个名称为entrance的entry类型的模块、一个名称为activities的feature类型的模块、一个名称为dynamics的动态共享模块和一个名称为statics的静态共享模块。在程序的主界面上显示多个跨模块引用字符串资源、图片资源,当点击主界面时,跨模块拉起UIAbility,并在新拉起的界面上调用其他模块的方法。11.4.2案例分析由于entrance模块要引用dynamics模块、statics模块中的字符串资源、图片资源,所以,需要在其oh-package.json5文件中模块依赖。同时,activities模块要引用dynamics模块中的方法,因此,需要在其oh-package.json5文件中模块依赖。通过这个案例,可以强化对模块依赖的理解和应用,同时,也可以看出鸿蒙平台模块的基本换份原则:其一,将用户交互界面放置在入口模块或者在feature类型模块中;其二,将业务功能实现代码放置在动态共享库或者静态共享库模块中。11.4.3案例实施新建名称为ch1102的工程,在工程中新建如下类型的模块:一个名称为entrance的entry类型的模块、一个名称为activities的feature类型的模块、一个名称为dynamics的动态共享模块和一个名称为statics的静态共享模块。然后,在dynamics模块的resource目录的media目录下放置名称为a01.jpg、a02.jpg的图片资源;在statics模块的resource目录的string.json中新增名称为static_str01值为“Hello”、称为static_str02值为“World”的字符串资源。完成后工程结构如图。修改后的statics模块的resource目录下的string.json文件内容如下:{"string":[{"name":"page_show","value":"pagefrompackage"},{"name":"static_str01","value":"Hello"},{"name":"static_str02","value":"World"}]}由于entrance模块要引用dynamics模块、statics模块的资源,因此,需要在其oh-package.json5文件中添加依赖。为此,修改oh-package.json5为如下内容:{"name":"entrance","version":"1.0.0","description":"Pleasedescribethebasicinformation.","main":"","author":"","license":"","dependencies":{"dynamics":"file:../dynamics","statics":"file:../statics"}}然后,修改entrance模块的Index.ets为如下内容:import{common,Want}from'@kit.AbilityKit';import{hilog}from'@kit.PerformanceAnalysisKit';import{BusinessError}from'@kit.BasicServicesKit';

@Entry@ComponentstructIndex{@Statemessage:string='[static].string.static_str01';@Stateimr:Resource=$r('[dynamics].media.a01');privatewhich:number=0;

privatestartUIAbility(){letwant:Want={bundleName:"com.example.ch1102",moduleName:"activities",abilityName:"ActivitiesAbility"};try{letcontext=this.getUIContext().getHostContext()ascommon.UIAbilityContext;context.startAbility(want).then(()=>{(0x0000,'ttt','startAbilitysuccess.');}).catch((err:BusinessError)=>{console.log(`startAbilityfailed.Code:${err.code},message:${err.message}`);})}catch(paramError){console.log(`Failed.Code:${paramError.code},message:${paramError.message}`);}}

build(){Column(){Image(this.imr).width('100%').height('250').margin(10).onClick(()=>{if(this.which%2==0)this.imr=$r('[dynamics].media.a02');elsethis.imr=$r

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论