前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >android中使用luaj

android中使用luaj

原创
作者头像
jiamiao
发布2019-11-28 17:18:01
2.3K0
发布2019-11-28 17:18:01
举报
文章被收录于专栏:蜗牛行者蜗牛行者

背景

开发中有一些场景,需要使用到动态化能力,除了插件和热补丁。我们还可以使用脚本,相比插件化与热补丁,脚本更加灵活的安全(Google对插件化持禁止态度),在android中常用的脚本有python和lua。

python因为包体较大、执行效率低等问题,在嵌入式android中使用较少。

lua虽然没有python那么强大,但是却有着三大优势,使得它非常适合在嵌入式设备中使用。

  • 包体小,luaj-3.0.1也就347KB,压缩后会更小。
  • 执行效率高
  • 内存占用小

本文主要讲述android与lua相互调用的问题。

android调用lua

首先我们准别一段lua脚本,这里我们采用vscode来编写,vscode可以编译、运行、单步调试lua脚本。在android运行lua前我们就可以确保lua脚本是没有问题,从而提高效率。

image.png
image.png

这里我们需要安装lua debug。配置方式可以参见文档https://blog.csdn.net/qq_35331967/article/details/83864437。这里需要注意的是,我们使用的luaj,所以有部分代码是编译不过的,调试的时候可以先去掉,例如:

image.png
image.png

然后我们尝试通过java代码来调用lua。

代码语言:txt
复制
Globals globals = JsePlatform.standardGlobals();

public void compile(File file) {
    try {
        globals.load(new FileReader(file), "script").call();
    } catch (FileNotFoundException e) {
        XLog.e(TAG, "compile: error", e);
    }
}

public Object invoke(String func, Object... parameters) {
    if (parameters != null && parameters.length > 0) {
        LuaValue[] values = new LuaValue[parameters.length];
        for (int i = 0; i < parameters.length; i++) {
            values[i] = CoerceJavaToLua.coerce(parameters[i]);
        }
        return globals.get(func).call(LuaValue.listOf(values));
    } else {
        return globals.get(func).call();
    }
}

这里有几点需要关注的:

  • 首先会创建Globals对象,这个对象负责加载lua文件。
  • invoke负责调用lua文件中的函数,func指函数名。parameters指参数,可以为多个。
  • 参数通过LuaValue.listOf转换为luatable,luatable是lua8种基础类型之一。
  • 一个文件一般对应一个Globals。

关于Globals,源码注释是这样描述的。

Global environment used by luaj. Contains global variables referenced by executing lua.

lua的文档比较少,有兴趣可以直接看源码,地址为:

https://github.com/luaj/luaj

这样我们就可以使用android直接调用lua了。

lua调用java

luaj中提供了5中方法可以用来访问java程序,这些方法定义在LuajavaLib中。

代码语言:txt
复制
public class LuajavaLib extends VarArgFunction {

	static final int INIT           = 0;
	static final int BINDCLASS      = 1;
	static final int NEWINSTANCE	= 2;
	static final int NEW			= 3;
	static final int CREATEPROXY	= 4;
	static final int LOADLIB		= 5;

	static final String[] NAMES = {
		"bindClass",
		"newInstance",
		"new",
		"createProxy",
		"loadLib",
	};
}

在lua中,我们可以直接用 : 号来访问方法。

bindclass

以在lua文件中输出log为例,注意当我们绑定log的类后,使用符号:来调用方法i,最终输出log。

代码语言:txt
复制
local log = luajava.bindClass("android.util.Log")
local tag = "main.lua"
log:i(tag, "file is nil")

newInstance

对于普通对象,我们先要实例化对象再调用方法,这里根据构造函数是否有参数,氛围两种。

注意这里同样使用符号:来调用对象的方法。

代码语言:txt
复制
javaObject = luajava.newInstance(类名全称)
javaObject = luajava.newInstance(类名全称,[构造方法参数(可变参数)])

//======
local dog = luajava.newInstance("com.water.Person")
dog:setName("3water")

local dog = luajava.newInstance("com.water.Person","3water")
dog:getName()

new

可以从源码中看出,newInstance与new非常的相似,new在创建class的时候,传入的参数是userdata,也就是java的class类。

代码语言:txt
复制
case NEWINSTANCE:
case NEW: {
    // get constructor
    final LuaValue c = args.checkvalue(1);
    final Class clazz = (opcode==NEWINSTANCE? classForName(c.tojstring()): (Class) c.checkuserdata(Class.class));
    final Varargs consargs = args.subargs(2);
    return JavaClass.forClass(clazz).getConstructor().invoke(consargs);
}

createproxy

通过createproxy,可以让lua继承java中的interface,从而获得对应的回调。

这里我们创建了一个TimeAnimator,当动画执行的时候,lua函数TimeListener.onTimeUpdate就会被回调。

代码语言:txt
复制
local timeAnimator = luajava.newInstance('android.animation.TimeAnimator')
local timeListener = luajava.createProxy('android.animation.TimeAnimator$TimeListener',TimeListener)
timeAnimator:setTimeListener(timeListener)

-- 实现回调
TimeListener = {}
function TimeListener.onTimeUpdate(animation,totalTime,deltaTime)
end

loadLib

loadlib这个还是用的比较少,应该是用来加载so文件,然后可以实现lua与c预研进行交互。

总结

lua作为一种轻量级语言,与其他语言结合后,在解决实际问题中会有非常多的好处。也会有一些缺点,比如资料较少,语法和java等有较大差异,开发者需要一段时间熟悉。但总的来说,还是非常推荐的。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 背景
  • android调用lua
  • lua调用java
    • bindclass
      • newInstance
        • new
          • createproxy
            • loadLib
              • 总结
              领券
              问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档