Android動態化方案調研
目前市面上存在以下幾種動態化的方案
l LUA
l 外掛化
l WebView
l React Native
l LUAView
l Weex
l 熱補丁
其中:
l 熱補丁的修復能力突出,無論目前存在的那種熱補丁形式,都會依賴於原始版本,和目標版本進行查分別叫,無法實現真正的動態化,而且隨著差異化的增加,風險越來越高,
l WebView的動態化能力簡單,三端統一便利,但是效能是主要的瓶頸,無法完成全部功能的替換。
l LUA動態化簡單,但是原始框架過於簡單,可以實現簡單的動態化,但是對於複雜的Android動態化功能,需要完全自己封裝一套中介軟體,工作量大,難度高。
l 外掛化,我們已經非常熟悉,無論使用還是設計,都不再需要花費時間來進行調研,只需要對比就好了。
上面幾個由於存在無法避免的問題,所以我們主要對LUAView,Weex, React Native進行調研,方便我們日後進行擴充套件,達到知己知彼,快速擴充套件的效果。
LuaView的原理及使用
簡介:LuaView並非是Lua,而是使用一種全新的解析器來解析Lua語言(用的開源框架luaj)。
首先拋棄LuaView的程式碼實現,設想我們自己設計一款程式碼解析器。
麻雀雖小,五臟具全,Lua的整體設計思路也是圍繞著這幾個模組進行的。
首先我們看一個簡單的Lua檔案
local screenWidth,screenHeight = System.screenSize()
-- Test Label
local label = Label()
label.text(System.ios() and "iOS" or "Android")
label.textColor(0x000000)
label.frame(0, 0, screenWidth, screenHeight)
label.textAlign(TextAlign.CENTER)
-- Test Button
local btn = Button()
btn.size(200, 200)
btn.text("Click Me")
btn.backgroundColor(0xff0000)
btn.callback(function()
Alert("Hello LuaView")
end)
其實看原始碼我們很容易發現實際上就是解析,顯示的流程,流程很簡單,主要是程式碼細節寫的很牛逼,簡單的流程如下。
所以我們綜上所訴,LuaView可以實現所有Androidapi上大部分的功能,不止是view的問題,無非就是擴充套件的問題,
所以我們實驗以下我們的假設,我們自定義語法
t = TT()
t.show(dddd)
顯示一個toast
首先加入binder
public class UITTBinderextends BaseFunctionBinder {
public UITTBinder() {
super("TT");
}
@Override
public Class<? extends LibFunction> getMapperClass() {
return UITTMethodMapper.class;
}
@Override
public LuaValue createCreator(LuaValue env,final LuaValue metaTable) {
return new BaseVarArgCreator(env.checkglobals(),metaTable, getMapperClass()) {
@Override
public LuaValue createUserdata(Globals globals,LuaValue metaTable, Varargs varargs) {
return new TTToast(globals, metaTable, varargs);
}
};
}
}
然後建立代理物件,
public class TTToastextends BaseUserdata {
public TTToast(Globals globals, LuaValue metaTable,Varargs varargs) {
super(globals, metaTable, varargs);
}
}
然後新增Toast的所有方法
public class UITTMethodMapper<Uextends TTToast> extends BaseMethodMapper<U> {
private static final String TAG = "UIToastMethodMapper";
private static final String[]sMethods = newString[]{
"show"//0
};
@Override
public List<String> getAllFunctionNames() {
return mergeFunctionNames(TAG,super.getAllFunctionNames(), sMethods);
}
@Override
public Varargs invoke(intcode, U target, Varargs varargs) {
final int optcode = code -super.getAllFunctionNames().size();
switch (optcode) {
case 0:
return show(target, varargs);
}
return super.invoke(code, target, varargs);
}
//--------------------------------------- API--------------------------------------------------
/**
* show a toast
*
* @param view
* @param varargs
* @return
*/
public LuaValue show(Uview, Varargs varargs) {
final CharSequence text = LuaViewUtil.getText(varargs.optvalue(2,NIL));
return ToastUtil.show(getContext(),text);
}
}
新增這幾個類就完成了,下一步我們需要在初始化的適合註冊binder
globals.tryLazyLoad(new UITTBinder());
這樣就完成了我們自定義TT欄位顯示Toast的功能。
在lua檔案中實驗一下,成功。
總結:綜上所述,LuaView的實現原理還是通過翻譯之後,執行api的程式碼,所以效率來看應該是很高的,只是有一些在反射,和程式碼邏輯呼叫的時候,多消耗了一些記憶體和效率,但是在繪製等問題上,完全是WebView無法比擬的,使使用者體驗可以接受的動態化方案。
當然缺點也是有的,除去上面所說的一些記憶體和效率問題外,主要的還是在專案構建的時候,替換的工作量是個不小的問題,需要將專案拆分,解耦,決定哪些功能使用luaView,完全從寫,是一個不小的工作量,
而且擴充套件也是個不小的工作量,他沒有辦法項Lua一樣,直接呼叫Android api,而是完全是自己封裝的,所以需要擴充套件的化,就要自己封裝,雖然架構比較清晰,擴充套件方便,但也是需要不小的工作量的。