作者:hanks https://juejin.im/post/5bf12c8751882511a8527ed4
做移動端開發,最蛋疼的就是不能動態發版,不能像 web 那樣發版立即全部用戶生效,然而 lua語言 爲其提供了可能性。lua 是一種腳本語言,使用 lua 來構建跨平臺原生應用有許多好處,比如 lua 語言簡潔高效,可移植性好, Lua虛擬機極爲輕量,僅佔用200到300k的內存空間,且速度極快。
演示
寫一個簡單的代碼演示一下。新建一個 lua 文件,叫做 view.lua, 放在手機的 sdcard 上,文件目錄爲 /sdcard/view.lua
require "import" import "android.widget.*" import "android.content.*" function getView() local layout = { LinearLayout, orientation = "vertical", layout_width = "fill", layout_height = "fill", { Button, id = "btn", layout_marginTop="8dp", layout_width = "fill", layout_height = "50dp", text = "click" }, } local view = loadlayout(layout) return view end
運行一下,
屏幕中上半部分是 Android 的 xml 佈局中寫好的代碼,當點擊運行按鈕時,加載 lua 腳本,返回一個 View 對象,然後添加到佈局中。一個簡單的 lua 腳本編寫的視圖就寫好了。 接下來修改一下,設置個點擊事件。
require "import" import "android.widget.*" import "android.content.*" function getView() local layout = { LinearLayout, orientation = "vertical", layout_width = "fill", layout_height = "fill", { Button, id = "btn", layout_marginTop="8dp", layout_width = "fill", layout_height = "50dp", text = "click" }, } local ids = {} -- store ids to find view local view = loadlayout(layout, ids) ids.btn.onClick = function() Toast.makeText(activity,"2333",0).show() end return view end
運行效果
再來個稍微複雜點的例子,寫個列表,新建 list.lua 文件,放在手機的 sdcard/list.lua
require "import" import "android.widget.*" import "android.content.*" import "android.view.View" import "androlua.LuaHttp" import "androlua.LuaAdapter" import "androlua.LuaImageLoader" local JSON = require("cjson") local uihelper = require('uihelper') -- create view table local layout = { LinearLayout, orientation = "vertical", layout_width = "fill", layout_height = "fill", { ListView, id = "listview", dividerHeight = 0, layout_width = "fill", layout_height = "fill", }, } local item_view = { FrameLayout, layout_width = "fill", layout_height = "240dp", { ImageView, id = "iv_image", layout_width = "fill", layout_height = "fill", scaleType = "centerCrop", }, { TextView, id = "tv_title", background = "#66000000", layout_width = "fill", layout_height = "fill", padding = "32dp", gravity = "center", maxLines = "5", lineSpacingMultiplier = '1.2', textSize = "14sp", textColor = "#CCFFFFFF", }, } local data = { dailyList = {} } local adapter local function getData() -- http://baobab.kaiyanapp.com/api/v1/feed local url = data.nextPageUrl if url == nil then url = 'http://baobab.kaiyanapp.com/api/v1/feed?udid=3e7ee30c6fc0004a773dc33b0597b5732b145c04' end if url:find('udid=') == nil then url = url .. '&udid=3e7ee30c6fc0004a773dc33b0597b5732b145c04' end print(url) LuaHttp.request({ url = url }, function(error, code, body) if error or code ~= 200 then print('fetch data error') return end local str = JSON.decode(body) uihelper.runOnUiThread(activity, function() data.nextPageUrl = str.nextPageUrl local list = str.dailyList[1].videoList for i = 1, #list do data.dailyList[#data.dailyList + 1] = list[i] end adapter.notifyDataSetChanged() end) end) end local function launchDetail(item) Toast.makeText(activity, item.title, 0).show() end function getView() local view = loadlayout(layout) adapter = LuaAdapter(luajava.createProxy("androlua.LuaAdapter$AdapterCreator", { getCount = function() return #data.dailyList end, getItem = function(position) return nil end, getItemId = function(position) return position end, getView = function(position, convertView, parent) position = position + 1 -- lua 索引從 1開始 if position == #data.dailyList then getData() end if convertView == nil then local views = {} -- store views convertView = loadlayout(item_view, views, ListView) if parent then local params = convertView.getLayoutParams() params.width = parent.getWidth() end convertView.setTag(views) end local views = convertView.getTag() local item = data.dailyList[position] if item then LuaImageLoader.load(views.iv_image, item.coverForFeed) views.tv_title.setText(item.title) end return convertView end })) listview.setAdapter(adapter) listview.setOnItemClickListener(luajava.createProxy("android.widget.AdapterView$OnItemClickListener", { onItemClick = function(adapter, view, position, id) launchDetail(data.dailyList[position + 1]) end, })) getData() return view end
複製代碼創建 listView , 設置 adapter ,網絡請求,刷新列表。看下效果吧。
代碼放到了 github
:https://github.com/hanks-zyh/luaDevAndroid
原理圖
寫了幾篇文章比較詳細的介紹了原理,想了解的可以看一下
Android 與 Lua 探究 lua 在 Android 中的應用 Lua 嵌入 Android 原理
支持 iOS 嗎?
Lua 是用 c 語言開發的,可移植性比較好,想支持 iOS 的話,原理時一樣的,不過參考目前已有的跨平臺技術。關於跨平臺方面的一些個人見解,目前已有的跨平臺技術每當涉及到不同平臺的特性時,事情就比較蛋疼了,需要單獨去適配,還有建立一堆連接庫,比如選取本地圖片,不同平臺的數據庫,平臺特有 api,真是一份代碼到處運行終是夢,一份兒代碼到處採坑纔是真。
Android 開發能支持到什麼程度?
看到了上面的原理圖就可以知道,支持 Android SDK 幾乎所有的 API。
— — — END — — —