调用javascript方法-鸿蒙OS开发手册:JS如何调用Java?

除了轻薄的智能穿戴设备外,鸿蒙目前支持的手机、汽车、电视、手表、平板电脑等都属于富鸿蒙。 JS语言项目中也有Java模块,它提供了JS跨语言调用Java方法的技术。

现在需要实现查看商品评论时长评论、中评论、短评论的比例统计。 这里请求评论数据,调用Java进行估算。

JS 调用 Java 有两种方式:Ability 和InternalAbility。 前者可以被不同的JS方法调用,后者适合与JS业务逻辑强相关、信噪比要求高的服务。 这里使用了能力的形式。

01

打造新服务能力

在项目工程目录的Java模块中,右键单击该项目的包调用javascript方法,新建→能力→清空服务能力。

在手动生成的众多重载方法中,我们需要使用的是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()是需要实现的主要业务方法,有四个参数:

02

完善的代码逻辑

规定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 result = new HashMap(5);
            if (code == LIST_COMMENTS) {
                // 获取并转化请求数据
                String req = data.readString();
                WordReq param = ZSONObject.stringToClass(req, WordReq.class);
                List 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;
        }
    }

}

03

JS端远程调用

Java服务部分已经写好了。 在JS中,鸿蒙为Java服务的单次请求提供了FeatureAbility.callAbility()方法。

其参数如下:

本例中,方法如下:

// 调用Java统计评论长度
    countWords() {
        let list = [];
        this.comments.forEach(e => {
            list.push(e.content);
        })
        FeatureAbility.callAbility({
            bundleName"com.example.litemall",
            abilityName".ServiceAbility",
            messageCode200,
            abilityType0,
            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中定义的一致。

跑步疗效:

但加入Java部分后调用javascript方法,项目编译速度明显变慢。 接下来的两步就花了很长时间。 有谁知道有什么办法可以加快速度吗?