從微信小程序到鴻蒙JS開(kāi)發(fā)-JS調(diào)用Java
想了解更多內(nèi)容,請(qǐng)?jiān)L問(wèn):
51CTO和華為官方合作共建的鴻蒙技術(shù)社區(qū)
除輕量級(jí)智能穿戴設(shè)備,現(xiàn)鴻蒙支持的手機(jī)、汽車(chē)、TV、手表、平板等屬于富鴻蒙,在JS語(yǔ)言的項(xiàng)目中也有Java模塊,并提供了JS跨語(yǔ)言調(diào)用Java方法的技術(shù)?,F(xiàn)需要實(shí)現(xiàn)查看商品評(píng)論時(shí),統(tǒng)計(jì)出長(zhǎng)評(píng)、中評(píng)和短評(píng)的比例,這里將評(píng)論數(shù)據(jù)請(qǐng)求來(lái)后調(diào)用Java進(jìn)行計(jì)算。
JS調(diào)用Java有Ability方式和Internal Ability方式兩種,前者可以被不同的JS方法調(diào)用,后者適用于與JS業(yè)務(wù)邏輯關(guān)聯(lián)性強(qiáng),響應(yīng)時(shí)延要求高的服務(wù)。這里采用Ability的方式。
1、新建一個(gè)Service Ability
在項(xiàng)目工程目錄Java模塊中,右鍵項(xiàng)目的包,New->Ability->Empty Service Ability。
在自動(dòng)生成的眾多重載方法中,我們需要用到的是onConnect()。此方法在首次連接時(shí)回調(diào),并返回IRemoteObject對(duì)象,用于后續(xù)的業(yè)務(wù)通信。
因此創(chuàng)建一個(gè)內(nèi)部類(lèi),繼承RemoteObject類(lèi)并實(shí)現(xiàn)IRemoteBroker接口。代碼框架如下:
- public class ServiceAbility extends Ability {
- private MyRemote remote = new MyRemote();
- @Override
- public IRemoteObject onConnect(Intent intent) {
- super.onConnect(intent);
- return remote.asObject();
- }
- static class MyRemote extends RemoteObject implements IRemoteBroker {
- MyRemote() {
- super("MyService_MyRemote");
- }
- MyRemote(String descriptor) {
- super(descriptor);
- }
- @Override
- public boolean onRemoteRequest(int code, MessageParcel data, MessageParcel reply, MessageOption option) {
- ......
- }
- @Override
- public IRemoteObject asObject() {
- return this;
- }
- }
- }
主要需實(shí)現(xiàn)的兩個(gè)方法是onRemoteRequest()和asObject()。在onConnect()方法中返回內(nèi)部類(lèi)的示例,asObject()直接返回this即可。onRemoteRequest()是主要需要實(shí)現(xiàn)的業(yè)務(wù)方法,有四個(gè)參數(shù):
- code:JS端請(qǐng)求時(shí)帶來(lái)的請(qǐng)求碼,可根據(jù)code進(jìn)行不同的業(yè)務(wù)處理。
- data:JS端請(qǐng)求時(shí)帶來(lái)的數(shù)據(jù),目前僅支持json格式。Java端通過(guò)data.readString()獲取請(qǐng)求json字符串。
- reply:Java端返回給JS端的數(shù)據(jù),目前僅支持String格式,通過(guò)reply.writeString(str)寫(xiě)入返回?cái)?shù)據(jù)。
- option:JS端指定同步或異步方式,Java端通過(guò)option.getFlag()獲取。
2、完善代碼邏輯
規(guī)定JS端每分頁(yè)加載一次評(píng)論數(shù)據(jù),就將目前頁(yè)面中的所有評(píng)論內(nèi)容發(fā)送給Java端進(jìn)行計(jì)算。流程和HTTP有一點(diǎn)類(lèi)似,獲取數(shù)據(jù)、處理數(shù)據(jù)、返回?cái)?shù)據(jù)。鴻蒙提供了ZSONObject可供處理json,完整邏輯代碼如下:
- public class ServiceAbility extends Ability {
- private MyRemote remote = new MyRemote();
- @Override
- public IRemoteObject onConnect(Intent intent) {
- super.onConnect(intent);
- return remote.asObject();
- }
- static class MyRemote extends RemoteObject implements IRemoteBroker {
- private static final int LIST_COMMENTS = 200;
- private static final int SUCCESS = 0;
- private static final int ERROR = 500;
- MyRemote() {
- super("MyService_MyRemote");
- }
- MyRemote(String descriptor) {
- super(descriptor);
- }
- @Override
- public boolean onRemoteRequest(int code, MessageParcel data, MessageParcel reply, MessageOption option) {
- Map<String, Object> result = new HashMap<>(5);
- if (code == LIST_COMMENTS) {
- // 獲取并轉(zhuǎn)化請(qǐng)求數(shù)據(jù)
- String req = data.readString();
- WordReq param = ZSONObject.stringToClass(req, WordReq.class);
- List<String> comments = param.getList().stream().filter(e -> !"用戶未填寫(xiě)評(píng)價(jià)內(nèi)容".equals(e)).collect(Collectors.toList());
- // 統(tǒng)計(jì)評(píng)論字?jǐn)?shù)
- int longComments = (int) comments.stream().mapToInt(String::length).filter(len -> len >= 200).count();
- int mediumComments = (int) comments.stream().mapToInt(String::length).filter(len -> len >= 30 && len < 200).count();
- int shortComments = (int) comments.stream().mapToInt(String::length).filter(len -> len < 30).count();
- // 計(jì)算占比
- DecimalFormat df = new DecimalFormat("#.00");
- double longPer = 1.0 * longComments / comments.size() * 100;
- double mediumPer = 1.0 * mediumComments / comments.size() * 100;
- double shortPer = 1.0 * shortComments / comments.size() * 100;
- // 返回結(jié)果
- result.put("long", df.format(longPer) + "%");
- result.put("medium", df.format(mediumPer) + "%");
- result.put("short", df.format(shortPer) + "%");
- result.put("code", SUCCESS);
- result.put("msg", "ok");
- reply.writeString(ZSONObject.toZSONString(result));
- return true;
- } else {
- result.put("code", ERROR);
- result.put("msg", "invalid code");
- reply.writeString(ZSONObject.toZSONString(result));
- return false;
- }
- }
- @Override
- public IRemoteObject asObject() {
- return this;
- }
- }
- }
3、JS端遠(yuǎn)程調(diào)用
Java服務(wù)部分寫(xiě)好了,在JS中,鴻蒙提供了FeatureAbility.callAbility()方法用于單次請(qǐng)求Java服務(wù)。其參數(shù)如下:
- bundleName:Ability包名,在config.json中,為app.bundleName。
- abilityName:調(diào)用服務(wù)端Ability類(lèi)名,可省略包名,直接寫(xiě)".XxxAbility"。
- messageCode:操作碼,和Java端的"code"參數(shù)相匹配。
- abilityType:Ability類(lèi)型,0為Ability,1為Internal Ability。
- data:請(qǐng)求數(shù)據(jù),json類(lèi)型。
- syncOption:與Java端"option"相匹配,0為同步方式,1為異步方式。默認(rèn)同步方式。
方法返回一個(gè)Promise對(duì)象,可通過(guò).then()和.catch()處理調(diào)用成功和異常。
本例中的方法如下:
- // 調(diào)用Java統(tǒng)計(jì)評(píng)論長(zhǎng)度
- countWords() {
- let list = [];
- this.comments.forEach(e => {
- list.push(e.content);
- })
- FeatureAbility.callAbility({
- bundleName: "com.example.litemall",
- abilityName: ".ServiceAbility",
- messageCode: 200,
- abilityType: 0,
- data: {
- list
- }
- }).then(res => {
- console.info(res);
- let data = JSON.parse(res);
- if (data.code == 0) {
- this.lengths[0].value = data.long;
- this.lengths[1].value = data.medium;
- this.lengths[2].value = data.short;
- }
- }).catch(res => {
- console.error(res);
- })
- }
Java端和JS端的代碼編譯完成并運(yùn)行,可以看到日志中的返回?cái)?shù)據(jù)和我們?cè)贘ava中定義的一致。
運(yùn)行效果:
但加上Java的部分后,項(xiàng)目編譯的速度明顯變慢了,如下兩步花了很長(zhǎng)時(shí)間,有沒(méi)有大神知道有沒(méi)有什么加速的方法?
想了解更多內(nèi)容,請(qǐng)?jiān)L問(wèn):
51CTO和華為官方合作共建的鴻蒙技術(shù)社區(qū)