1. 程式人生 > >Android動態化方案調研

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,而是完全是自己封裝的,所以需要擴充套件的化,就要自己封裝,雖然架構比較清晰,擴充套件方便,但也是需要不小的工作量的。