• 从微信小程序到鸿蒙js开发【15】——JS调用Java


    鸿蒙入门指南,小白速来!0基础学习路线分享,高效学习方法,重点答疑解惑--->【课程入口】

    目录:
    1、新建一个Service Ability
    2、完善代码逻辑
    3、JS端远程调用
    4、《从微信小程序到鸿蒙js开发》系列文章合集

    除轻量级智能穿戴设备,现鸿蒙支持的手机、汽车、TV、手表、平板等属于富鸿蒙,在JS语言的项目中也有Java模块,并提供了JS跨语言调用Java方法的技术。现需要实现查看商品评论时,统计出长评、中评和短评的比例,这里将评论数据请求来后调用Java进行计算。

    JS调用Java有Ability方式和Internal Ability方式两种,前者可以被不同的JS方法调用,后者适用于与JS业务逻辑关联性强,响应时延要求高的服务。这里采用Ability的方式。

    1、新建一个Service Ability

    在项目工程目录Java模块中,右键项目的包,New->Ability->Empty Service Ability。

    从微信小程序到鸿蒙js开发【15】——JS调用Java

    在自动生成的众多重载方法中,我们需要用到的是onConnect()。此方法在首次连接时回调,并返回IRemoteObject对象,用于后续的业务通信。

    因此创建一个内部类,继承RemoteObject类并实现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;
            }
        }
    
    }

    主要需实现的两个方法是onRemoteRequest()和asObject()。在onConnect()方法中返回内部类的示例,asObject()直接返回this即可。onRemoteRequest()是主要需要实现的业务方法,有四个参数:

    • code:JS端请求时带来的请求码,可根据code进行不同的业务处理。
    • data:JS端请求时带来的数据,目前仅支持json格式。Java端通过data.readString()获取请求json字符串。
    • reply:Java端返回给JS端的数据,目前仅支持String格式,通过reply.writeString(str)写入返回数据。
    • option:JS端指定同步或异步方式,Java端通过option.getFlag()获取。

    2、完善代码逻辑

    规定JS端每分页加载一次评论数据,就将目前页面中的所有评论内容发送给Java端进行计算。流程和HTTP有一点类似,获取数据、处理数据、返回数据。鸿蒙提供了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) {
                    // 获取并转化请求数据
                    String req = data.readString();
                    WordReq param = ZSONObject.stringToClass(req, WordReq.class);
                    List<String> comments = param.getList().stream().filter(e -> !"用户未填写评价内容".equals(e)).collect(Collectors.toList());
                    // 统计评论字数
                    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();
                    // 计算占比
                    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;
                    // 返回结果
                    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端远程调用

    Java服务部分写好了,在JS中,鸿蒙提供了FeatureAbility.callAbility()方法用于单次请求Java服务。其参数如下:

    • bundleName:Ability包名,在config.json中,为app.bundleName。
    • abilityName:调用服务端Ability类名,可省略包名,直接写".XxxAbility"。
    • messageCode:操作码,和Java端的"code"参数相匹配。
    • abilityType:Ability类型,0为Ability,1为Internal Ability。
    • data:请求数据,json类型。
    • syncOption:与Java端"option"相匹配,0为同步方式,1为异步方式。默认同步方式。

      方法返回一个Promise对象,可通过.then()和.catch()处理调用成功和异常。

    本例中的方法如下:

    // 调用Java统计评论长度
        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端的代码编译完成并运行,可以看到日志中的返回数据和我们在Java中定义的一致。

    从微信小程序到鸿蒙js开发【15】——JS调用Java

    运行效果:从微信小程序到鸿蒙js开发【15】——JS调用Java

    从微信小程序到鸿蒙js开发【15】——JS调用Java

    但加上Java的部分后,项目编译的速度明显变慢了,如下两步花了很长时间,有没有大神知道有没有什么加速的方法?

    从微信小程序到鸿蒙js开发【15】——JS调用Java从微信小程序到鸿蒙js开发【15】——JS调用Java

    作者:Chris.
    想了解更多内容,请访问: 51CTO和华为官方战略合作共建的鸿蒙技术社区https://harmonyos.51cto.com

  • 相关阅读:
    js完美拖拽封装及其案例
    js运动框架封装以及两种案例
    js常见的11种兼容
    Lua 学习笔记(五)函数
    Lua 学习笔记(四)语句与控制结构
    Lua 学习笔记(三)表达式
    Lua 学习笔记(二)语法、类型、值
    Lua 学习笔记(一)环境搭建
    Cocos2d-x 3.2 学习笔记(十六)保卫萝卜 游戏主循环与定时器
    Cocos2d-x 3.2 学习笔记(十五)保卫萝卜 场景与数据
  • 原文地址:https://www.cnblogs.com/HarmonyOS/p/14441015.html
Copyright © 2020-2023  润新知