Tip:

In recent development, I encountered a requirement that a JavaScript formula was returned in the background, and the value of TextView was required to be calculated by the formula and changed by the number continuously, similar to the implementation of timer

Let's say the background returns one"S*4", the current TextView value is 1, so the calculated TextView value should be 1, 4, 16, 64...Copy the code

Question: How do I calculate JavaScript formulas without using WebView controls in the UI?

B:

The author didn’t have access to this requirement at that time, so I didn’t know how to start. Later, I thought that the native JavaScript engine in Java background could realize this, so why not try it in Android?

JavaScript engine

At present, there are two main methods to run JavaScript on Android/iOS: one is to use the browser components WebView (Android) and UIWebView/WKWebView (iOS); Another approach is to compile and integrate a full-featured JavaScript engine.

In App development, WebView is often used to load a web page or even build a complete application. Currently, there are many related frameworks and tools, such as Cordova to build multi-platform applications. When we have high performance and experience requirements, Inefficient JS parsing in WebViews (depending on the JavaScript engine), slow DOM rendering (depending on the rendering engine), and high system fragmentation for API support (depending on the browser kernel) often affect performance bottlenecks and development experiences.

At present, there are many solutions based on high performance JavaScript engines, such as React Native, Weex, NativeScript, Tabrisjs, etc. Each solution has some differences, but they all need the support of the underlying JavaScript engine. To understand how these upper-layer frameworks work, we first need to understand the basics of a JavaScript engine.

  • A JavaScript engine is a virtual machine that specializes in JavaScript scripting and is typically shipped with a web browser. The main JavaScript engines that can run on Android and iOS are JavaScriptCore, V8, SpiderMonkey, and Rhino. JavaScriptCore is a JavaScript provided in WebKit The open source framework for the engine, which is currently maintained by Apple and used in Safari and integrated into iPhone with iOS7. Because it is written in C, it cannot be used directly in Android development. AndroidJSCore, an open source project on Github (now defunct, the official repository points to LiquidCore), helps developers use JavaScriptCore by calling Java interfaces.
  • V8 is a high-performance open source JS engine developed and maintained by Google. It is written in C++ and runs on Google Chrome. Like JavaScriptCore, in Android development, interfaces need to be called through a layer of wrapping. J2V8, an open source project on Github, encapsulates V8 in Java based on JNI, which we’ll focus on below.
  • SpiderMonkey was originally developed by Netscape and is now developed and maintained by Mozilla, and is widely used in Mozilla products such as FireFox. SpiderMonkey provides some core JavaScript data types, such as numbers, strings, arrays, objects, and so on, as well as some methods, such as array.push. It also makes it easy for each application to expose its own objects and methods to JavaScript code. The application developer can decide how the application exposes the objects associated with the script being written.
  • Rhino is an open source JAVASCRIPT engine developed by Mozilla. It is written in Java, so it can be called directly. In JDK 6 and JDK 7, Rhino is bundled with the engine.
  • Nashorn was developed and maintained by Oracle. Starting in JDK 8, Rhino was replaced by Nashorn as the JDK default JS engine. Nashorn is available with JDK8 and is open source and performs better than Rhino, but does not support the Android Dalvik VM.
From the JS engine alone, Rhino does not need to go through JNI and uses less memory, but it is very inefficient; Engines developed in C, such as V8 and JavaScriptCore, are far superior to those developed in Java, such as Rhino, but require a Java wrapper layer and have JNI call performance issues. J2V8 and AndroidJSCore two packaging layer: J2V8 availability, reliability, robustness is better; AndroidJSCore still has a number of performance issuesCopy the code

Need to implement

  • V8 engine

implementation 'com. Eclipsesource. J2v8: j2v8:5.0.103 @ aar'
Copy the code

Special note: V8 engine packages are around 15M in each CPU architecture (ARM64-V8A, Armeabi-V7A, Armeabi, x86)

  • Rhino

implementation 'IO. Apisense: rhino - android: 1.0'
Copy the code
// proguard obfuscation -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.**Copy the code

Rhino packages are around 140K