想了解更多内容,请访问:

专注于为中小企业提供成都网站建设、网站建设服务,电脑端+手机端+微信端的三站合一,更高效的管理,为中小企业资中免费做网站提供优质的服务。我们立足成都,凝聚了一批互联网行业人才,有力地推动了上千多家企业的稳健成长,帮助中小企业通过网站建设实现规模扩充和转变。
和华为官方合作共建的鸿蒙技术社区
https://harmonyos.
上一篇“HarmonyOS UI框架关键技术解析”中,给大家介绍了基于JS/JAVA UI框架开发简单业务的方法。那么对于复杂业务,在当前HarmonyOS版本下,如何基于JS UI框架来开发呢?
通常一个典型使用JS UI框架的HarmonyOS应用开发模型如下图1所示:
图1 典型应用开发模型
HarmonyOS的用户应用程序包APP由一个或多个Hap包组成。每个Hap可以包含一个或多个Ability。Ability分为两种类型:Feature Ability(简称FA)和Particle Ability(简称PA),FA和PA是HarmonyOS应用的基本组成单元,能够实现特定的业务功能。FA有UI界面,而PA无UI界面。FA有多种展现形式,如普通界面形式Page Ability,服务卡片形式Form等,一般使用JS 语言实现前台界面。PA支持ServiceAbility和Data Ability。ServiceAbility提供后台运行任务的能力,如处理复杂后台任务等。Data Ability用于对外部提供统一的数据访问抽象。这两个Ability一般使用Java 语言实现。
当前HarmonyOS Ability具体分类信息如下:
JS UI框架提供的声明式编程,使应用开发更加简单,但当前HarmonyOS JS API还不够丰富,无法处理数据等更复杂的业务。为了达到处理复杂业务,同时保证业务数据和UI的解耦,一般会将复杂逻辑放到PA中即JAVA端实现,而界面交互则放到FA中的UI部分即JS端实现,如图1所示。
这就涉及到FA(JS端)与PA(JAVA端)的交互,为此,Harmony OS JS UI框架提供了JS FA(Feature Ability)调用JAVA PA(Particle Ability)的机制,该机制提供了一种通道来传递方法调用、处理数据返回以及订阅事件上报。
下面我们通过一两个例子来解释该方法涉及的技术原理。
为支持ACE开发框架一次开发,跨平台运行的目标,采用了接口拓展机制打通前端应用层和后端平台层。JS UI框架提供了一种自动封装平台能力扩展API的机制,让应用开发者轻松调用API即能完成JS端到JAVA端的传递方法调用、处理数据返回以及订阅事件上报。
图2 模块框架模型
如图2所示,当前HarmonyOS支持JS作为前端应用开发语言,提供API接口,供开发者实现业务逻辑,通过类似接口拓展机制将JS层的参数传递到平台层(Native),同时在平台层提供插件代码(Plugin Native code)供三方平台实现业务逻辑。
JS FrameWork
提供API用于传递方法调用,数据流通信,以及订阅事件回调。并通过JsBridge桥接起C++ 与JS,JsBridge主要负责加载JS代码,运行在QJS Engine上,将JS代码通过全局函数桥接到C++ 上,并将C++的结果返回给JS层。
QJS Engine
QuickJS 是一个轻量且可嵌入的 JavaScript 引擎,包括模块、异步生成器和代理。
ACE Framework
将JS的消息往平台层透传,将JS数据转换成C++ 类型的数据,再通过C++ 与JAVA的JNI接口类,将C++的数据传递到JAVA侧,并接收JAVA侧返回的数据。
Native
负责平台层数据编解码,并根据解码后得到的FunctionName调用第三方开发者的插件代码逻辑。
HarmonyOS API
平台层提供JAVA端API接口。开发者实现JAVA端对应接口的业务逻辑。
JS UI框架当前提供了Ability和Internal Ability两种FA调用PA的方式:
这两种调用方式在代码中可通过abilityType来标识,具体使用差异见下表:
FA调用PA注意事项:
下面来给大家详细介绍JS FA调用JAVA PA的开发方法。
图3 FA调用PA开发方法
如图3所示,当FeatureAbility Plugin收到JS调用请求后,系统根据开发者在JS接口中设置的参数如指定的abilityType(Ability或Internal Ability),来选择对应的方式进行处理。开发者在onRemoteRequest()中实现PA提供的业务逻辑,不同的业务通过业务码来区分。
FA端
1.Channel JS API提供以下模块能力:
用于传递方法调用的类,通常用于上层应用者调用native中的某个方法而定义使用。调用callNative()方法即可将function以及对应的参数传递到平台层,需要在Native层也适配相应的逻辑代码。
简言之,即ModuleGroup实现JS调用JAVA方法,提供的JS API如下:
√ 调用PA能力,FeatureAbility.callAbility(OBJECT)
用于数据流通信,通常用于平台层触发的Native事件通知应用层。在应用层调用subscribe()方法注册回调事件启动监听平台,调用unSubscribe()取消平台监听。第三方开发者在平台层需要适配相应的逻辑代码。
简言之,即EventGroup实现JAVA回调JS,提供的JS API如下:
2.FeatureAbility Plugin
主要完成方法调用、数据流的参数传递(编解码)、线程切换、JNI转换等处理。
其主要提供以下2个重点模块:
用于Internal Ability的管理,包括注册管理等,注册后的Internal Ability与FA共生命周期。
JS端与JAVA端通过接口扩展机制进行通信,通过bundleName和abilityName来进行关联。
PA端提供以下两类接口:
Ability调用方式,FA使用远端进程通信拉起并请求PA服务。
Internal Ability调用方式,采用内部函数调用的方式和FA进行通信。
图4 JS FA调用JAVA PA过程(Ability方式)
1.FA JS端指定PA的调用方式及相关消息码和内容,调用PA(订阅PA类似)。设置bundleName,abilityName,abilityType等。
2.PA JAVA端响应:
通过Ability方式拉起的PA继承自Ability,FA在请求PA服务时会连接到PA,连接成功后,PA在onConnect返回一个remote对象(RemoteObject),用于FA向PA发送消息。remote对象实现onRemoteRequest方法,用于响应FA端的请求。
示例代码如下:e.g.两数求和
FA端 (Ability方式)
- // abilityType: 0-Ability; 1-Internal Ability
 - const ABILITY_TYPE_EXTERNAL = 0;
 - const ABILITY_TYPE_INTERNAL = 1;
 - // syncOption(Optional, default sync): 0-Sync; 1-Async
 - const ACTION_SYNC = 0;
 - const ACTION_ASYNC = 1;
 - const ACTION_MESSAGE_CODE_PLUS = 1001;
 - export default {
 - plus: async function() {
 - var actionData = {};
 - actionData.firstNum = 1024;
 - actionData.secondNum = 2048;
 - // 请求参数,abilityName、bundleName、messageCode、abilityType、actionData需要求和的2个入参
 - var action = {};
 - action.bundleName = 'com.example.hiaceservice';
 - action.abilityName = 'com.example.hiaceservice.ComputeServiceAbility';
 - action.messageCode = ACTION_MESSAGE_CODE_PLUS;
 - action.data = actionData;
 - // 使用ability方式
 - action.abilityType = ABILITY_TYPE_EXTERNAL;
 - action.syncOption = ACTION_SYNC;
 - // FA调用PA
 - var result = await FeatureAbility.callAbility(action);
 - var ret = JSON.parse(result);
 - if (ret.code == 0) {
 - console.info('plus result is:' + JSON.stringify(ret.abilityResult));
 - } else {
 - console.error('plus error code:' + JSON.stringify(ret.code));
 - }
 - }
 - }
 
PA端(Ability方式)
- public class ComputeServiceAbility extends Ability {
 - private MyRemote remote = new MyRemote();
 - // FA在请求PA服务时会连接PA,连接成功后,需要在onConnect返回一个remote对象,供FA向PA发送消息
 - @Override
 - protected IRemoteObject onConnect(Intent intent) {
 - super.onConnect(intent);
 - return remote.asObject();
 - }
 - // remote对象的实现,完成消息请求处理,回传
 - class MyRemote extends RemoteObject implements IRemoteBroker {
 - private static final int SUCCESS = 0;
 - private static final int ERROR = 1;
 - private static final int PLUS = 1001;
 - MyRemote() {
 - super("MyService_MyRemote");
 - }
 - @Override
 - public boolean onRemoteRequest(int code, MessageParcel data, MessageParcel reply, MessageOption option) {
 - switch (code) {
 - // 消息码PLUS
 - case PLUS: {
 - // 消息参数解析
 - String dataStr = data.readString();
 - RequestParam param = new RequestParam();
 - try {
 - param = ZSONObject.stringToClass(dataStr, RequestParam.class);
 - } catch (RuntimeException e) {
 - HiLog.error(LABEL, "convert failed.");
 - }
 - // 返回结果设置
 - Map
 result = new HashMap (); - result.put("code", SUCCESS);
 - result.put("abilityResult", param.getFirstNum() + param.getSecondNum());
 - // 返回结果回传
 - reply.writeString(ZSONObject.toZSONString(result));
 - break;
 - }
 - default: {
 - Map
 result = new HashMap (); - result.put("abilityError", ERROR);
 - reply.writeString(ZSONObject.toZSONString(result));
 - return false;
 - }
 - }
 - return true;
 - }
 - @Override
 - public IRemoteObject asObject() {
 - return this;
 - }
 - }
 - }
 
图5 JS FA调用JAVA PA过程(Internal Ability方式)
1.FA JS端指定PA的调用方式及相关消息码和内容,调用PA(订阅PA类似)。设置bundleName,abilityName,abilityType等。
2. PA JAVA端响应:
通过Internal Ability方式拉起的PA需要继承自AceInternalAbility,且需要在AceAbility中注册该Internal Ability(AceAbility中执行register方法)。
PA中通过setInternalAbilityHandler方法注册onRemoteRequest方法,用于响应FA端的请求。
示例代码如下:e.g.两数求和
FA端(Internal Ability方式)
和使用ability方式代码类似,区别是需要改变方式类型为Internal Ability:
action.abilityType = ABILITY_TYPE_INTERNAL;
PA端(Internal Ability方式):
- //Internal Ability注册:在MainAbility注册
 - public class MainAbility extends AceAbility {
 - @Override
 - public void onStart(Intent intent) {
 - // 注册, 如果需要在Page初始化(onInit或之前)时调用AceInternalAbility的能力,注册操作需要在super.onStart之前进行
 - ComputeInternalAbility.register(this);
 - ...
 - super.onStart(intent);
 - }
 - @Override
 - public void onStop() {
 - // 注销
 - ComputeInternalAbility.unregister();
 - super.onStop();
 - }
 - }
 
在JAVA目录下实现InternalAbility(此处为ComputeInternalAbility)
- public class ComputeInternalAbility extends AceInternalAbility {
 - private static final String BUNDLE_NAME = "com.example.hiaceservice";
 - private static final String ABILITY_NAME = "com.example.hiaceservice.ComputeInternalAbility";
 - private static final int SUCCESS = 0;
 - private static final int ERROR = 1;
 - private static final int PLUS = 1001;
 - private static ComputeInternalAbility instance;
 - private AbilityContext abilityContext;
 - // 如果多个Ability实例都需要注册当前InternalAbility实例,需要更改构造函数,设定自己的bundleName和abilityName
 - public ComputeInternalAbility() {
 - super(BUNDLE_NAME, ABILITY_NAME);
 - }
 - public boolean onRemoteRequest(int code, MessageParcel data, MessageParcel reply, MessageOption option) {
 - switch (code) {
 - case PLUS: {
 - String dataStr = data.readString();
 - RequestParam param = new RequestParam();
 - try {
 - param = ZSONObject.stringToClass(dataStr, RequestParam.class);
 - } catch (RuntimeException e) {
 - HiLog.error(LABEL, "convert failed.");
 - }
 - // 返回结果当前仅支持String,对于复杂结构可以序列化为ZSON字符串上报
 - Map
 result = new HashMap (); - result.put("code", SUCCESS);
 - result.put("abilityResult", param.getFirstNum() + param.getSecondNum());
 - // SYNC
 - if (option.getFlags() == MessageOption.TF_SYNC) {
 - reply.writeString(ZSONObject.toZSONString(result));
 - } else {
 - // ASYNC
 - MessageParcel responseData = MessageParcel.obtain();
 - responseData.writeString(ZSONObject.toZSONString(result));
 - IRemoteObject remoteReply = reply.readRemoteObject();
 - try {
 - remoteReply.sendRequest(0, responseData, MessageParcel.obtain(), new MessageOption());
 - } catch (RemoteException exception) {
 - return false;
 - } finally {
 - responseData.reclaim();
 - }
 - }
 - break;
 - }
 - default: {
 - Map
 result = new HashMap (); - result.put("abilityError", ERROR);
 - reply.writeString(ZSONObject.toZSONString(result));
 - return false;
 - }
 - }
 - return true;
 - }
 - /** * Internal ability 注册接口。 */
 - public static void register(AbilityContext abilityContext) {
 - instance = new ComputeInternalAbility();
 - instance.onRegister(abilityContext);
 - }
 - private void onRegister(AbilityContext abilityContext) {
 - this.abilityContext = abilityContext;
 - this.setInternalAbilityHandler((code, data, reply, option) -> {
 - return this.onRemoteRequest(code, data, reply, option);
 - });
 - }
 - /** * Internal ability 注销接口。 */
 - public static void unregister() {
 - instance.onUnregister();
 - }
 - private void onUnregister() {
 - abilityContext = null;
 - this.setInternalAbilityHandler(null);
 - }
 - }
 
以上代码样例只是关键部分,完整代码样例可参考官网资料【JS FA如何调用PA】:
JS FA如何调用PA
https://developer.harmonyos.com/cn/docs/documentation/doc-guides/ui-js-fa-call-pa-0000001050435961
本文介绍了JS FA(Feature Ability)调用JAVA PA(Particle Ability)的机制和使用场景,基于JS UI框架开发的应用可以使用该机制完成更丰富的功能。未来HarmonyOS会持续丰富完善JS API,为开发者提供更便捷的API能力。
想了解更多内容,请访问:
和华为官方合作共建的鸿蒙技术社区
https://harmonyos.
                文章名称:JS UI框架下FA与PA是如何交互的
                
                文章来源:http://www.csdahua.cn/qtweb/news44/97744.html
            
网站建设、网络推广公司-快上网,是专注品牌与效果的网站制作,网络营销seo公司;服务项目有等
声明:本网站发布的内容(图片、视频和文字)以用户投稿、用户转载内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。文章观点不代表本网站立场,如需处理请联系客服。电话:028-86922220;邮箱:631063699@qq.com。内容未经允许不得转载,或转载时需注明来源: 快上网