最近開發中遇到一種需求,後臺返回一個JavaScript公式,要求TextView的值帶入公式計算並不斷進行數字變化,相似於定時器的實現javascript
好比後臺返回一個"S*4",當前TextView的值位1,那麼計算事後的TextView的值應該是1,4,16,64...
複製代碼
做者當時也沒有接觸過這種需求,因此一時間也無從下手,後來聯想到Java後臺的原生JavaScript 引擎能夠實現,何不在Android中嘗試下呢?java
目前在 Android/iOS 上運行 JavaScript,主要有兩種方法:一種方法是利用系統的瀏覽器組件 WebView(Android)和 UIWebView/WKWebView(iOS);另外一種方法是編譯和集成一個功能全面的 JavaScript 引擎。android
在 App 開發中常常會使用 WebView 加載一個網頁,甚至構建一個完整應用,目前相關的框架和工具也比較多,例如使用 Cordova 構建多平臺應用。當咱們對於性能和體驗要求比較高的時候,WebView 中解析 JS 的效率低(取決於 JavaScript 引擎)、DOM 渲染慢(取決於渲染引擎)以及系統碎片化嚴重對於 API 支持也不盡相同(取決於瀏覽器內核)每每影響性能瓶頸和開發體驗。api
目前基於高性能 JavaScript 引擎的方案也有不少,如 React Native、weex、NativeScript、Tabrisjs 等,每一個方案之間都有一些不同的地方,不過都離不開底層 JavaScript 引擎的支持。要想了解這些上層框架的原理,咱們首先須要瞭解 JavaScript 引擎的基本內容。數組
- JavaScript 引擎是一個專門處理 JavaScript 腳本的虛擬機,通常會附帶在網頁瀏覽器之中。在 Android 和 iOS 中能夠運行的最主要的 JavaScript 引擎有 JavaScriptCore、V八、SpiderMonkey、Rhino JavaScriptCore 是一個在 WebKit 中提供 JS 引擎的開源框架,目前該引擎由 Apple 維護,使用於 Safari 瀏覽器,iOS7 後也集成到了 iPhone 平臺。因爲其使用 C 語言編寫,所以在 Android 開發中並不能直接使用。Github 上的開源項目 AndroidJSCore(目前已經中止維護了,官方倉庫指向LiquidCore) 可以幫助開發者通過調用 Java 接口而使用 JavaScriptCore。
- V8 是由 Google 開發並維護的高性能開源 JS 引擎,採用 C++編寫,使用於 Google Chrome 瀏覽器。同 JavaScriptCore 同樣,在 Android 開發中,相關接口須要經過一層包裝進行調用。Github 上的開源項目 J2V8 基於 jni 實現了 Java 對 V8 的封裝,下文咱們重點介紹一下。
- SpiderMonkey 最初由 Netscape 開發,現在由 Mozilla 開發並維護,且被普遍用於 Mozilla 產品(如 FireFox)。SpiderMonkey 提供了一些核心的 JavaScript 數據類型,如數字,字符串,數組,對象等等,以及一些方法如 Array.push。它還使得每一個應用程序都容易將其本身的對象和方法暴露給 JavaScript 代碼。應用開發者能夠決定應用如何將與所寫腳本相關的對象暴露出來。
- Rhino 是由 Mozilla 開發的開源 JS 引擎,採用 Java 編寫,所以能夠直接調用,在 JDK 六、JDK 7 中更是捆綁了該引擎,其提供的特性包括:
- Nashorn 由 Oracle 開發並維護,從 JDK 8 開始,Rhino 被 Nashorn 代替,成爲 JDK 默認 JS 引擎。Nashorn 同 JDK8 一同發佈和開源,較 Rhino 而言性能更好,但不支持 Android Dalvik 虛擬機。
單從 JS 引擎來講,Rhino 執行不須要經過 JNI 且佔用更少的內存,但執行效率很低;V8 和 JavaScriptCore 等 C 語言開發的引擎
遠勝於 Rhino 等 Java 開發的引擎,但須要一層 Java 包裝層,並存在 JNI 調用性能問題。
就 J2V8 和 AndroidJSCore 兩個包裝層而言:J2V8 的可用性、可靠性、健壯性更優;AndroidJSCore 還存在着很多的性能問題
複製代碼
implementation 'com.eclipsesource.j2v8:j2v8:5.0.103@aar'
複製代碼
特別注意:在每一個CPU架構(arm64-v8a、armeabi-v7a、armeabi、x86)中 V8引擎包都在15M上下瀏覽器
implementation 'io.apisense:rhino-android:1.0'
複製代碼
// proguard混淆
-keep class com.sun.script.** {*;}
-keep class sun.misc.** {*;}
-keep class sun.reflect.** {*;}
-keep class sun.security.** {*;}
-dontwarn org.mozilla.javascript.**
-dontwarn org.mozilla.classfile.**
-keep class org.mozilla.javascript.** { *; }
-keep class com.sun.phobos.** {*;}
-keep class javax.script.**
複製代碼
Rhino包大體在140k上下bash