入坑的的原因是大佬想解决动态下发问题,当初觉得这个SDK能解决问题,就派我去调研这个东西...然而调研总是要出一些东西产出的,当时我查了下,全网写关于这个SDK的文章真的非常少,所以就有了这篇文章。先把基友网地址发出来:https://alibaba.github.io/LuaViewSDK/guide.html
我个人认为 这玩意就是为了解决动态下发的问题,然后封装了各端代码,最起码我们是用来解决动态下发问题的。
首先,简单介绍下,LuaViewSDK入门难么?答案不难。有点经验的开发人员,入门2天吧,第一天看看lua的基本语法,第二天对着api挨个实验就行了。然而...我真的不建议大家使用这个。因为在2020年的今天,这个项目已经好几年没维护了。Latest commit on 14 Aug 2017。项目现在没人维护,不过当初用在聚划算项目上,也算我辈膜拜的程度。
简单说下我入坑的过程,第一天 我了解下啥是lua,装lua环境,毕竟不会就虚的很。第二天觉得自己差不多掌握了基本语法,开始往AS倒SDK包(这里我踩坑了,报错很多,毕竟三年的项目了,如果项目使用的androidX更麻烦)。第三天,我各种踩坑,但是能基本写点东西了。基本就这样子,接下来,我按照我当初的步骤一步步写出来。
windows安装环境请自行百度(虽然我在家也是windows,心疼下我为写代码买的主机)。我将在mac端一步步自己重新开始,再写出来。
1 先到官网 http://www.lua.org/download.html

点击下载,然后随便自己建个文件夹扔进去。(下面是我复制别人的,但是我实验了好用)
解压之后,命令行cd
进入到src
目录下,输入make macosx
完成后cd ..
到上一层目录, 输入sudo make install
然后 输入 lua,显示出版本号,这就成功了。

接下来编辑器问题,我本来想用subLime,但是本渣渣灰一直把这神器当文本文档用。
这里有个插件叫EmmyLua,我在windows上就用的这个 贼好使
我在mac上继续沿用。打开AS,然后点击左上角Mac图标右边的Android Studio按钮,在弹出的功能选项中点击Preferences,找到Plugins,然后输入EmmyLua,install,然后重启ok。
然后, 新建assets文件夹,在assets 上,右键,新建,new Lua File ,写下下面的代码,右键run xx.lua,然后下面就出来了hello wordl。
local name ="hello wordl"
print(name)
到这里我感慨了下,还是mac牛逼,我在windows上还得配下sdk环境,这都不用直接就能跑了 - -!
如果你安装出啥问题了,就度娘下,windows怎么装的我忘记了,反正最好还得配置下sdk路径,我用mac居然不用了,感觉美滋滋。
接下来是lua的简单语法,大神直接略过。也可看菜鸟窝相关的东西,(https://www.runoob.com/lua/lua-tutorial.html),我第一天看的不是特别懂,我还特地找了本书(Lua程序设计随便给个下载地址 http://www.downcc.com/soft/313218.html )。看了一晚上,然后我就学会了最基本的语法,比如for 循环啊,table啊,因为LuaViewSDK并非纯lua,所以不用那么学特别多。其实真当你使用sdk的时候发现最常用的就是 local 和冒号(调用方法) 。
接下来下载导入LuaViewSDK,下载地址:https://github.com/alibaba/LuaViewSDK,直接downLoad。因为我是搞android的,IOS我就不管了。down的时候,可以先去建个新的项目,一会用来练手。
下载下来,熟练解压,LuaViewSDK-master 中Android文件夹下的LuaViewSDK,这下面才是我们要用的东西。别运行那个demo了,反正我没运行起来。我们不是新建了个项目么。
File -New -import Model ,将那个导入到项目
倒完包,发现运行不起来了,这是正常的,淡定淡定。根据报错,挨个排查。
//找到LuaViewSDK的AndroidManifest文件 将minSdkVersion 删除掉
<uses-sdk android:minSdkVersion="14" />
这是我改的LuaViewSDK的build.gradle
apply plugin: 'com.android.library'
description = """LuaView-Android: 用lua写Android、iOS"""
repositories {
mavenLocal()
mavenCentral()
jcenter()
}
configurations {
providedCompile
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'com.android.support:support-v4:23.0.1'
//recycler view
implementation 'com.android.support:recyclerview-v7:23.0.1'
// compile 'com.android.support:appcompat-v7:23.4.0'
}
/*
定义android插件
*/
android {
compileSdkVersion 23
defaultConfig {
minSdkVersion 21
targetSdkVersion 29
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
sourceSets {
main {
jniLibs.srcDirs = ['libs']
manifest.srcFile 'AndroidManifest.xml'
java.srcDirs = ['src', 'src-csslayout']
resources.srcDirs = ['src']
aidl.srcDirs = ['src']
renderscript.srcDirs = ['src']
res.srcDirs = ['res']
assets.srcDirs = ['assets']
}
debug.setRoot('build-types/debug')
release.setRoot('build-types/release')
}
packagingOptions {
exclude 'META-INF/LICENSE.txt'
}
buildTypes {
debug {
debuggable true
}
}
lintOptions {
abortOnError false
}
}
因为新建的项目一般版本比较高默认使用androidX,可以将版本向下压制一下,
如果不想使用androidX 可以将gradle.properties 下面属性改为false
android.useAndroidX=false
# Automatically convert third-party libraries to use AndroidX
android.enableJetifier=false
这是我项目app下的build.gradle配置
apply plugin: 'com.android.application'
android {
compileSdkVersion 29
buildToolsVersion "29.0.3"
defaultConfig {
applicationId "com.leo.luademotest"
minSdkVersion 21
targetSdkVersion 29
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'com.android.support.constraint:constraint-layout:1.1.3'
testImplementation 'junit:junit:4.12'
implementation 'com.android.support:support-v4:23.0.1'
//recycler view
implementation 'com.android.support:recyclerview-v7:23.0.1'
// androidTestImplementation 'androidx.test:runner:1.2.0'
// androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
implementation project(':LuaViewSDK')
}
现在如果编译还有什么错,那就按照报错提示修改,可能buildtools版本不一样,修改下就可以了。现在我这里是可以跑起来了。接下来看LuaViewSDK相关的东西。
首先先拉平一个概念,就是LuaView 你就把他当成一个Andeoid中的View去用就行。这样理解比较简单。
LuaVIew创建的方式
//直接创建
LuaView luaView= LuaView.create(getContext());
//异步创建
LuaView async = LuaView.createAsync(getContext());
// 异步创建 带回调监听 推荐第三种
LuaView.createAsync(getContext(), new LuaView.CreatedCallback() {
@Override
public void onCreated(LuaView luaView) {
}
});
LuaViewConfig 配置(按需设置)
LuaViewConfig.init(this);//初始化,只需要调用一次
LuaViewConfig.setDebug(true);//设置是否debug,默认release模式下不会开启
LuaViewConfig.setOpenDebugger(false);//是否开启调试器,默认模拟器环境会开启,真机不会开启。TODO Android 真机调试
LuaViewConfig.setAutoSetupClickEffects(true);//是否自动设置点击效果(如果有点击事件会自动设置)...
加载本地lua文件
在assets下创建xxx.lua文件,点击运行就在页面上看到一个按钮。
public class MainActivity extends Activity {
private LinearLayout llContent;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
llContent = findViewById(R.id.ll_content);
LuaView.createAsync(this, new LuaView.CreatedCallback() {
@Override
public void onCreated(LuaView luaView) {
luaView.load("button.lua");
llContent.addView(luaView);
}
});
}
}
lua文件
local btn= Button();
btn:title("lua的title")
下面简称LuaViewSDK为lua,一般业务上的需求大体可以分为以下几类,
- 纯lua加载
- Lua和native交互
- native和lua交互
- 拓展view。
我也将按照上面四个进行编写对应代码,因为我没服务器可以搭建,暂时全部加载本地lua进行展示
代码我会上传到github上,到时候大家下载就可以了。
- 纯lua加载
我将以最常用的图片Image 和按钮Button,写一个简单的demo
//获取屏幕宽高
w, h = System.screenSize();
local unit = w * 1.0 / 360 * 1.0;
//这里需要将本地图片放到deawable下,可以直接引用
local hongbao ="hongbao_bg";
//用来加载的网络图片
local opneUrl="https://xossimg.2cq.com/system/img/play/newbies/b22e4ef39c0968e65ca893604d303b15.png"
//设置还没打开的图片的宽高
local img_noOepn =Image();
img_noOepn:image(hongbao)
img_noOepn:frame(0,100*unit,252*unit,319*unit)
img_noOepn:alignCenterHorizontal();
//设置加载图片的宽高
local redAward =Image();
redAward:image(opneUrl)
redAward:frame(0,100*unit,252*unit,319*unit)
redAward:alignCenterHorizontal();
redAward:hide();
//设置点击的按钮宽高和位置和图片 title
local btnOpen =Button();
btnOpen:alignCenterHorizontal();
btnOpen:frame(0,350*unit,150*unit,34*unit)
btnOpen:image("btn_yellow_bg","btn_yellow_bg")
btnOpen:title("去往直播间")
btnOpen:titleColor("0xff2233")
btnOpen:hide();
//点击第一张图片 显示奖励红包 添加点击事件
img_noOepn:onClick( function ()
img_noOepn :hide() redAward:show();btnOpen:show() end)
这里因为涉及到图片加载的问题,LuaViewSDK中并没有直接提供图片加载的框架,而是提供了对外的接口
//这里是一个静态方法,设置完以后全局可用
LuaView.registerImageProvider(ImageProvider)
public class GlideImageProvider implements ImageProvider {
private static final String TAG = "GlideImageProvider";
//加载的时候
@Override
public void load(Context context, WeakReference<BaseImageView> imageView, String url, WeakReference<DrawableLoadCallback> callback) {
ImageView imageView1 = imageView.get();
Glide.with(context).load(url).into(imageView1);
}
//重新加载
@Override
public void preload(Context context, String url, DrawableLoadCallback callback) {
}
//不可见的时候
@Override
public void pauseRequests(ViewGroup view, Context context) {
}
//可见的时候
@Override
public void resumeRequests(ViewGroup view, Context context) {
}
}
直接设置LuaView.registerImageProvider(GlideImageProvider)就可以了。我这里面使用的Glide,如何引用Gilde这里我就不做赘述了。对了如果你的手机是高版本手机,比如9和9以上,可能加载非https的图片出不来,是因为android在高版本做了安全限制,具体解决方案度娘就可以了。
多提一嘴,写点击事件的模板是
view:onClick( function ()
todoxxx() end)
- Lua和native交互
lua和native交互需要注册一个方法
提供一个类 当做lua和native交互的桥梁,在下面类里面我提供了一个startAcitvity的方法。
/**
* 被lua打开的页面
* 测试lua和本地交互
*/
public class LuaOpenNativeBridge {
private Activity mActivity;
public LuaOpenNativeBridge(Activity activity) {
this.mActivity = activity;
}
/**
* 被lua调用的方法
*/
public void startAcitvity() {
Intent intent = new Intent();
intent.setClass(mActivity, LuaOpenNativeActivity.class);
mActivity.startActivity(intent);
}
}
luaView.load("newbies.lua");
//注册桥 前面的名字使用来在lua脚本中使用,后面是你的桥类
luaView.register("luaopnenative", new LuaOpenNativeBridge(LuaViewActivity.this));
//注册图片加载(全局一次就可以建议放在初始化)
LuaView.registerImageProvider(GlideImageProvider.class);
//将luaview 添加到布局
llAll.addView(luaView);
还是拿上面的lua做案例,直接在最后按钮上添加点击事件。看最后的代码就可以了
w, h = System.screenSize();
local unit = w * 1.0 / 360 * 1.0;
local hongbao ="hongbao_bg";
local opneUrl="https://xossimg.2cq.com/system/img/play/newbies/b22e4ef39c0968e65ca893604d303b15.png"
local img_noOepn =Image();
img_noOepn:image(hongbao)
img_noOepn:frame(0,100*unit,252*unit,319*unit)
img_noOepn:alignCenterHorizontal();
local redAward =Image();
redAward:image(opneUrl)
redAward:frame(0,100*unit,252*unit,319*unit)
redAward:alignCenterHorizontal();
redAward:hide();
local btnOpen =Button();
btnOpen:alignCenterHorizontal();
btnOpen:frame(0,350*unit,150*unit,34*unit)
btnOpen:image("btn_yellow_bg","btn_yellow_bg")
btnOpen:title("去往直播间")
btnOpen:titleColor("0xff2233")
btnOpen:hide();
img_noOepn:onClick( function ()
img_noOepn :hide() redAward:show();btnOpen:show() end)
//添加点击事件
btnOpen:onClick( function ()
redAward :hide() btnOpen:hide() Toast("拉取接口,打开直播间")
//这里的名字和 注册的名字一样,直接掉对应注册类里的方法
luaopnenative:startAcitvity() end)
- native和lua交互
有时候 我们也希望和lua进行对应的互动 ,这里涉及到一个类LVCustomPanel
这是我写的一个代码,initPanel方法中,写需要做的事情,我这里添加了一个文本输入框,当我输入框,输入东西的时候,我希望lua可以给我吐司出来,回调lua 要用到callLuaCallback 方法。callLuaCallback方法是个可变函数,可以将需要的参数回传给lua
public class NativeOpenLua extends LVCustomPanel {
private EditText edInput;
private static final String TAG = "NativeOpenLua";
public NativeOpenLua(Globals globals, LuaValue metaTable, Varargs varargs) {
super(globals, metaTable, varargs);
}
@Override
public void initPanel() {
LayoutInflater localinflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View view = localinflater.inflate(R.layout.view_nativeopennative, null, false);
edInput = view.findViewById(R.id.edinput);
view.findViewById(R.id.btn_send).setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
String showContent = edInput.getText().toString();
if (!TextUtils.isEmpty(showContent)) {
callLuaCallback(showContent);
} else {
ToastUtil.showToast(getContext(), "大佬,输入点啥子嘞");
}
}
});
LayoutParams relativeLayoutParamsMM = LuaViewUtil.createRelativeLayoutParamsMM();
addView(view,relativeLayoutParamsMM);
}
}
lua那边就很简单,收到消息就吐司出来
//这里要对应注册的panel名称
panel = NativeOpenLua()
panel:frame(0, 0, w, h)
//回调 对应的参数
panel:callback(function(message)
local showContent =
Toast("lua显示 您输入的消息为 "..message)
end)
print("rootView", panel.nativeView().getAlpha())
中间需要一个桥来沟通
luaView.registerPanel(NativeOpenLua.class);
luaView.load("nativeopenlua.lua");
llAll.addView(luaView);}
4 拓展view
可能SDK 中包含的View 不够在支撑自己的业务,那么就需要自己添加view到lua中
其实扩展比较简单 ,还是集成LVCustomPanel,在initPanel中将自己写的好view 添加到lua中就可以了
**
* 显示扩展
*/
public class ShowCustomePanel extends LVCustomPanel {
public ShowCustomePanel(Globals globals, LuaValue metaTable, Varargs varargs) {
super(globals, metaTable, varargs);
}
@Override
public void initPanel() {
LayoutInflater localinflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View view = localinflater.inflate(R.layout.view_customepanel, null, false);
view.findViewById(R.id.img_show).setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
callLuaCallback("点击去往直播间");
}
});
LayoutParams relativeLayoutParamsMM = LuaViewUtil.createRelativeLayoutParamsMM();
//添加view
addView(view, relativeLayoutParamsMM);
}
}
注册,registerPanel 这里是多构造函数,可以取名字,也可以不取别名,我直接将ShowCustomePanel注册进去。区别在lua脚本里。
luaView.registerPanel(ShowCustomePanel.class);
luaView.load(luaUrl);
panel = ShowCustomePanel()
panel:frame(0, 0, w, h)
panel:callback(function(message)
Toast("即将打开直播间")
luaopnenative:startAcitvity()
end)
是不是发现拓展居然和native和lua交互 基本是一样的?其实想想也是,我都能和lua交互了,我怎么不能把一个view 塞给lua呢。只不过这里的pannel 直接指向了你扩展的view,在这里你的view可以受用lua提供的各种方法,比如size,frame等等方法。
到这里基本就讲解完了LuaViewSDK的入门。如果有其他需求可以去看看api如何使用。有时间我会挨个实验下SDK的Api,财了坑我再同步。
网友评论