前言

uni-app是一个开源前端框架,是用vue.js开发的,可以实现跨平台的开发。地址:https://github.com/dcloudio/uni-app
而Native.js是使用uni-app开发时可以用到的一种开发技术,以下介绍摘自《5+ App开发Native.js入门指南》:http://ask.dcloud.net.cn/article/88
本文只是对上面这个文章的一些摘抄和提炼,方便Android开发者参考。

Native.js技术,简称NJS,是一种将手机操作系统的原生对象转义,映射为JS对象,在JS里编写原生代码的技术。
NJS编写的代码,最终需要在HBuilder里打包发行为App安装包,或者在支持Native.js技术的浏览器里运行。目前Native.js技术不能在普通手机浏览器里直接运行。

  • NJS大幅扩展了HTML5的能力范围,原本只有原生或Hybrid App的原生插件才能实现的功能如今可以使用JS实现。
  • NJS大幅提升了App开发效率,将iOS、Android、Web的3个工程师组队才能完成的App,变为1个web工程师就搞定。
  • NJS不再需要配置原生开发和编译环境,调试、打包均在HBuilder里进行。没有mac和xcode一样可以开发iOS应用。

再次强调,Native.js不是一个js库,不需要下载引入到页面的script中,也不像nodejs那样有单独的运行环境,Native.js的运行环境是集成在5+runtime里的,使用HBuilder打包的app或流应用都可以直接使用Native.js。

简言之,Native.js可以实现用js语法来调用Android或者ios的功能,以实现一处开发,多处运行的目的。使用HBuilder这个开发工具完成功能开发后,需要把打包数据放入Android项目或者ios项目里,然后就可以编译得到Android或者ios安装包。
HBuilder工具下载地址:https://www.dcloud.io/hbuilderx.html

本文主要介绍Native.js如何配合Android开发。

简单示例

以一个简单的例子说明一下Native.js的使用:
如果Android 项目里有个工具类ToastUtil.java是用来管理Toast的,其中有个静态方法用来显示Toast:

package com.example.demo;
public static void show(Context ctx, CharSequence msg, int duration) {
	XXX
}

在Android项目里,如果是这样用的:

ToastUtil.show(MainActivity.this, "提醒一下", Toast.LENGTH_LONG);

对应到了native.js里,写法就是这样:

var ToastUtil = plus.android.importClass("com.example.demo.ToastUtil");
var Toast = plus.android.importClass("android.widget.Toast");
ToastUtil.show(plus.android.runtimeMainActivity(), "提醒一下", Toast.LENGTH_LONG);

其中plus.android.importClass是用来导入类的,然后由于ToastUtil类的show方法是静态方法,Toast类的LENGTH_LONG是静态常量,所以都是可以用类后面跟点号来使用的。plus.android.runtimeMainActivity()是用来获取当前的activity。详细语法后面会讲,这里先大概有个印象。

当然上面的写法如果运行在ios平台上就会出错了,所以在native.js里,得针对不同操作系统做判断:

switch ( plus.os.name ) {  
    case "Android":  
        // Android平台: plus.android.*  
        var ToastUtil = plus.android.importClass("com.example.demo.ToastUtil");
		var Toast = plus.android.importClass("android.widget.Toast");
		ToastUtil.show(plus.android.runtimeMainActivity(), "提醒一下", Toast.LENGTH_LONG);
        break;  
    case "iOS":  
        // iOS平台: plus.ios.*  
        break;  
    default:  
        // 其它平台  
        break;  
    }  

如果还有兴趣继续看下去的话,接下来就是详细讲解了。


用法详解

以一个更全面的例子来讲解,下面是一个测试类:

package io.dcloud;  

// 定义类NjsHello  
public class NjsHello {  
    // 静态常量  
    public static final int CTYPE = 1;  
    // 静态变量  
    public static int count;  
    // 成员常量  
    public final String BIRTHDAY = "2013-01-13";  
    // 成员变量  
    String name; //定义属性name  
    NjsHelloEvent observer;  
    public void updateName( String newname ) { //定义方法updateName  
        name = newname;  
    }  
    public void setEventObserver( NjsHelloEvent newobserver ) {  
        observer = newobserver;  
    }  
    public void test() { //定义方法test  
        System.out.printf( "My name is: %s", name );  
        observer.onEventInvoked( name );  
    }  
    public static void testCount() {  
        System.out.printf( "Static count is:%d", count );  
    }  
    static{  // 初始化类的静态变量  
        NjsHello.count = 0;  
    }  
}  

这是上面的代码中用到的接口类:

package io.dcloud;  

// 定义接口NjsHelloEvent  
public interface NjsHelloEvent {  
    public void onEventInvoked( String name );  
}  

下面看如何在native.js中使用这个测试类:

· 导入类后获取类的静态常量属性

// 导入测试类NjsHello  
var NjsHello = plus.android.importClass("io.dcloud.NjsHello");  
// 获取类的静态常量属性  
var type = NjsHello.CTYPE;  

· 导入类后调用类的静态方法

// 导入测试类NjsHello  
var NjsHello = plus.android.importClass("io.dcloud.NjsHello");  
// 调用类的静态方法  
NjsHello.testCount();  

· 导入类后获取类的静态变量值

// 导入测试类NjsHello  
var NjsHello = plus.android.importClass("io.dcloud.NjsHello");  
// 获取类的静态变量 
var count = NjsHello.plusGetAttribute( "count" );  
console.log( "NjsHello Static's value: "+count ); // 输出“NjsHello Static's value: 0”  

· 导入类后设置类的静态属性值

// 导入测试类NjsHello  
var NjsHello = plus.android.importClass("io.dcloud.NjsHello");  
// 设置类的静态属性值  
NjsHello.plusSetAttribute( "count", 2 );  
console.log( "NjsHello Static's value: "+NjsHello.plusGetAttribute( "count" ) ); // 输出“NjsHello Static's value: 2”  

· 导入类创建实例对象,调用对象的方法

// 导入测试类NjsHello  
var NjsHello = plus.android.importClass("io.dcloud.NjsHello");  
// 创建NjsHello的实例对象  
var hello = new NjsHello();  
// 调用对象的方法  
hello.updateName( "Tester" );  
// ...  

· 导入类创建实例对象,获取对象的常量属性

// 导入测试类NjsHello  
var NjsHello = plus.android.importClass("io.dcloud.NjsHello");  
// 创建NjsHello的实例对象  
var hello = new NjsHello();  
// 访问对象的常量属性  
var birthday = hello.BIRTHDAY;  
console.log( "NjsHello Object Final's value: "+birthday ); // 输出“NjsHello Object Final's value: 2013-01-13”  
// ...  

· 导入类创建实例对象,获取对象的属性值

// 导入测试类NjsHello  
var NjsHello = plus.android.importClass("io.dcloud.NjsHello");  
// 创建对象的实例  
var hello = new NjsHello();  
hello.updateName( "Tester" );  
// 获取其name属性值  
var name = hello.plusGetAttribute( "name" );  
console.log( "NjsHello Object's name: "+name );  // 输出“NjsHello Object's name: Tester”  
// ...  

· 导入类创建实例对象,设置对象的属性值

// 导入测试类NjsHello  
var NjsHello = plus.android.importClass("NjsHello");  
// 创建对象的实例  
var hello = new NjsHello();  
// 设置其name属性值  
hello.plusSetAttribute( "name", "Tester" );  
console.log( "NjsHello Object's name: "+hello.plusGetAttribute("name") ); // 输出“NjsHello Object's name: Tester”  
// ...  

· 实现接口,并触发接口中函数的运行

// 导入测试类NjsHello  
var NjsHello = plus.android.importClass("io.dcloud.NjsHello");  
// 实现接口“NjsHelloEvent”对象  
var hevent = plus.android.implements( "io.dcloud.NjsHelloEvent", {  
"onEventInvoked":function( name ){  
    console.log( "Invoked Object’s name: "+name ); // 输出“Invoked Object’s name: Tester”  
}  
} );  
// 创建对象的实例  
var hello = new NjsHello();  
// 调用updateName方法  
hello.updateName( "Tester" );  
// 设置监听对象  
hello.setEventObserver( hevent );  
// 调用test方法,触发代理事件  
hello.test(); // 触发上面定义的匿名函数运行  
// ...  

高级用法

有前述的常用API,已经可以完成各项业务开发。此处补充的高级API,是在熟悉NJS后,为了提升性能而使用的API。高级API无法直接用“.”操作符使用原生对象的方法,在debug时也无法watch原生对象,但高级API性能高于常规API。
虽然导入类对象(plus.android.importClass和plus.ios.importClass)后,可以方便的通过“.”操作符来访问对象的常量、调用对象的方法,但导入类对象也需要消耗较多的系统资源,所以在实际开发时应该尽可能的减少导入类对象,以提高程序效率。

如果我们不导入类对象则无法通过new操作符实例化类对象,这时可通过plus.ios.newObject()、plus.android.newObject()方法来创建实例对象。

注意:由于没有导入类对象,所以通过此方法创建的实例对象无法通过“.”操作符直接调用对象的方法,而必须使用plus.android.invoke方法来调用。

· 不导入类创建实例对象

// 不调用plus.android.importClass("io.dcloud.NjsHello")导入类NjsHello  
// 创建对象的实例  
var hello = plus.android.newObject( "io.dcloud.NjsHello" );  
// ...  

· 不导入类对象获取类的静态常量属性

// 不调用plus.android.importClass("io.dcloud.NjsHello")导入类NjsHello  
// 访问类的静态常量属性  
var type = plus.android.getAttribute( "io.dcloud.NjsHello", "CTYPE" );  
console.log( "NjsHello Final's value: "+type ); // 输出“NjsHello Final's value: 1”  
// ...  

· 不导入类对象,创建实例对象,并获取其name属性值

// 不调用plus.android.importClass("io.dcloud.NjsHello")导入类NjsHello  
// 创建对象的实例  
var hello = plus.android.newObject( "io.dcloud.NjsHello" );  
// 获取其name属性值  
var name = plus.android.getAttribute( hello, "name" );  
console.log( "NjsHello Object's name: "+name );  // 输出“NjsHello Object's name: Tester”  
// ...  

· 不导入类对象设置类的静态属性值

// 不调用plus.android.importClass("io.dcloud.NjsHello")导入类NjsHello  
// 设置类的静态属性值  
plus.android.setAttribute( "io.dcloud.NjsHello", "count", 2 );  
console.log( "NjsHello Static's value: "+plus.android.getAttribute("io.dcloud.NjsHello","count") ); // 输出“NjsHello Static's value: 2”  
// ...  

· 不导入类对象,创建实例对象,并设置其name属性值

// 不调用plus.android.importClass("io.dcloud.NjsHello")导入类NjsHello  
// 创建对象的实例  
var hello = plus.android.newObject( "io.dcloud.NjsHello" );  
// 设置其name属性值  
plus.android.setAttribute( hello, "name", "Tester" );  
console.log( "NjsHello Object's name: "+hello.plusGetAttribute("name") ); // 输出“NjsHello Object's name: Tester”  
// ...  

· 不导入类对象,调用类的静态方法

// 不调用plus.android.importClass("io.dcloud.NjsHello")导入类NjsHello  
// 调用类的静态方法  
plus.android.invoke( "io.dcloud.NjsHello", "testCount" );  
// ...  

· 不导入类对象,创建实例对象,并调用其updateNmae方法

在这里插入代码片// 不调用plus.android.importClass("io.dcloud.NjsHello")导入类NjsHello  
// 创建对象的实例  
var hello = plus.android.newObject( "io.dcloud.NjsHello" );  
// 调用updateName方法  
plus.android.invoke( hello, "updateName", "Tester" );  
console.log( "NjsHello Object's name: "+hello.getAttribute("name") ); // 输出“NjsHello Object's name: Tester”  
// ...  

关于Native.js调用其它Android系统功能,可以看这里:https://ask.dcloud.net.cn/article/114

本文是从这篇讲解里提炼出来的,如果有问题,可以查看原文:
http://ask.dcloud.net.cn/article/88

Logo

前往低代码交流专区

更多推荐