introduce

React Native has revived the topic of cross-platform mobile development. It was once thought that cross-platform development could be implemented on mobile phones using Web technologies just like desktop development, but most of them were abandoned due to performance or functionality issues and had to develop multiple versions for different platforms.

But that hasn’t stopped people from exploring cross-platform development techniques. After all, who doesn’t want to reduce development costs and run everything at once? In addition to React Native, many other solutions have emerged in recent years. In this article, I will provide technical analysis of these solutions for interested readers.

For the sake of discussion, I’ve broken them down into the following four major genres:

  • Web Flow: Also known as Hybrid technology, it is based on Web-related technologies to implement interfaces and functions
  • Transcoding flow: Convert a language to Objective-C, Java, or C#, and develop it using official tools for different platforms
  • Compile flow: Compiles a language to a binary file, generates a dynamic library, or packages it as an APK/IPA/XAP file
  • Virtual machine flow: Runs by porting virtual machines in one language to different platforms

Web flow

Web streams are well known. PhoneGap/Cordova, for example, wraps a native interface and exposes it to JavaScript. It can run in a WebView or build a Chrome kernel.

It’s been a hot topic of debate over the years, and there’s been a lot of discussion online about it, so I’ll focus on the performance issue that people are most concerned about.

Web streams are most often mocked for being slow (in this case, the performance of embedded HTML, regardless of network load times), but why slow? The common perception is that “DOM is slow,” but from a browser implementation point of view, DOM exposes the apis for manipulating documents to JavaScript, and JavaScript calls these apis into the internal C++ implementation with little performance cost. So in theory, the BROWSER DOM must be faster than the Android “DOM”, because most of the Android presentation architecture is written in Java, under the premise of realizing the same function, C++ is unlikely to be slower than Java (in some cases it is possible to do JIT compilation optimizations better, but only in the minority).

So the “DOM is slow” statement is not true in the literal sense, but it’s probably common because most people don’t know much about browser implementations other than that browsers have the DOM, so you can only blame it for any problems.

So what’s the problem? It seems to me that there are three problems:

  • Early browsers were poorly implemented and not optimized
  • CSS is too complex and time-consuming to calculate
  • DOM provides too limited an interface to optimize

The first problem is the most critical and the most difficult to solve. When it comes to the poor Web performance, it is mainly said that it is poor under Android, but it is very smooth under iOS. Before Android 4, WebView does not even realize GPU acceleration, and the whole page is redrawn every time. Not when there’s animation.

Browser optimizations can wait until Android 4.4 becomes more popular, since Chrome will be used for rendering after 4.4.

For the latest browsers, the main reason for the slow rendering is the second problem: CSS is too complex, because there is no fundamental difference between Chrome and Android View in terms of implementation principles, but CSS is too flexible and has too many features, so the computation cost is high, which naturally makes it slower.

Can that be solved by simplifying CSS? In fact, some people try to do this, such as Famo.us. The main feature of famo.us is that it does not allow you to write CSS, but only uses fixed layout methods, and relies entirely on JavaScript to write the interface, so it can effectively avoid writing inefficient CSS, thus improving performance.

For complex interfaces and super-long listviews common in mobile phones, the third problem will be more prominent, because DOM is a very high-level API, which makes JavaScript unable to control memory and thread as fine-grained as Native, so it is difficult to optimize. It will be more obvious on machines with poor hardware. We tried embedding native Components to solve this problem a year ago, but this solution depends on the support of the application side. Maybe the browser will come with several optimized Web Components, which can solve the performance problem well.

At present, these three problems are difficult to solve, so some people want to draw the interface by themselves without HTML/CSS. For example, React Canvas can be drawn directly on canvas. However, in my opinion, this is only the solution to part of the problems at this stage. As a historical note, Bespin did this six years ago when browsers were still slow, and the project was superseded by ACE, which uses THE DOM. Mainstream editors like TextMirror and Atom now use DOM directly. Even someone in W3C wrote a special article teasing the disadvantages of using Canvas as editor, so be careful when using Canvas.

Besides Canvas, some people think that WebGL is fast and try to draw on WebGL, such as HTML-GL, but its current implementation is too lazy. Simply speaking, HTML2Canvas is used to render DOM nodes into pictures. I then put this image as a texture in WebGL, which is equivalent to implementing something that the browser wrote in C++ in JavaScript, which is definitely slower, but I can fool people with GLSL effects.

Hardware acceleration is not the same as “fast.” If you think hardware acceleration is necessarily faster than software, you should learn computer architecture

In fact, in addition to the performance problem, I think the more serious problem in Web flow is the lack of functionality. For example, iOS 8 added 4000+ API, while Web standards require a long process of writing and reviewing, I can’t wait for 4000 API in my life. Even Cordova cannot be packaged by itself, so writing Native code is a must in order to better use the new features of the system.

P.S. Although I mentioned that HTML/CSS is so complex that it causes performance problems, this is actually the biggest advantage of the Web, because the original purpose of the Web is to display documents. If you want to display rich graphics, iOS/Android both have rich text components, but they are nowhere near as good as CSS. Therefore, it is inevitable to embed the Web in many Native applications.

Transcoding flow

As mentioned above, it is necessary to write Native code, but the official languages of different platforms are different, which will cause the same logic to be written more than twice. Therefore, some people think of ways to reduce the workload through code conversion, such as converting Java to Objective-C.

This way it sounds aren’t readily available, but it’s cost and risk are the smallest, because after the code conversion can with official offer a variety of tools, and common development difference is not big, so don’t have to worry about all sorts of weird problems, but need to pay attention to whether the generated code to be read, don’t consider unreadable solutions.

Let’s take a look at some of the ways code conversion exists today.

Convert Java to Objective-C

J2objc’s ability to convert Java code into Objective-C is said to be used internally at Google to reduce cross-platform development costs. The Google Inbox project, for example, claims to share 70% of the code with it.

You might wonder why Google developed a tool to help you write Objective-C. In fact, I think Google is doing a good job, because basically all the important apps will be developed for Android and iOS at the same time, and having this tool means that you can develop for Android first and then for iOS…

Given the success stories, this solution is worth a try, and the key is that there are a lot of Java people who can use it to quickly port code to Objective-C.

Convert Objective-C to Java

In addition to Java to Objective-C, there is also an objective-C to Java solution, MyAppConverter, which is more ambitious than the previous J2objC tool and also intends to include the UI part, As you can see from its converted list, there are also UIKit, CoreGraphics, and other components that make it possible for some applications to convert without changing their code, but I’m not optimistic about this and it’s not realistic for most applications.

Since it is a charging project at present, I have not tried it and do not understand the technical details, so I will not make comments here.

Convert Java to C#

Mono provides a Java code into C# tool, but seems to use a lot of people, Star only 118, so it looks unreliable.

JUniversal is a tool that can convert Java to C#, but there is no public version of JUniversal, so the details remain to be seen. It features a simple cross-platform library, including file handling, JSON, HTTP, OAuth components, It can be used to develop reusable business logic.

The conversion to C# looks very immature compared to the conversion to Objective-C and Java, and is likely to be used by fewer people than Windows Phone.

Convert Haxe to another language

When it comes to source code conversion, Haxe is a strange language that doesn’t have its own virtual machine or executable compiler, so it has to be converted to another language. Support for conversion to Neko (bytecode), Javascript, Actionscript 3, PHP, C++, Java, C#, and Python is currently unofficial, although there are implementations of conversion to Swift. Support for iOS development is currently only available through Adobe AIR.

OpenFL has a cross-platform game engine that can eventually be drawn using HTML5 Canvas, OpenGL or Flash. OpenFL’s development experience is pretty good. The same line of code can compile executable files for different platforms without modification. Since it is compiled by converting to C++, it has advantages in terms of performance and decompilation. Unfortunately, it does not seem to be stable enough at present, or it could be a competitive advantage for cocos2d-x.

There is also a cross-platform UI component called HaxeUI on top of OpenFL, but the interface style I find so ugly that it is only usable in games.

So for now, Haxe might work for cross-platform game development, but not for APP development, and sharing code on it is even less likely, since few developers are familiar with it, adding to the cost.

XMLVM

In addition to the source-to-source conversion mentioned earlier, XMLVM takes the unusual step of first converting bytecode into an XML-based intermediate format and then using XSL to generate different languages, Currently supports generation of C, Objective-C, JavaScript, C#, Python, and Java.

While being based on an intermediate bytecode makes it easy to support multiple languages, it also causes the generated code to be unreadable because the syntactic sugar in many languages is irreversibly erased in the bytecode. Here is a simple example of objective-C code generated that looks like assembly:

XMLVM_ENTER_METHOD("org.xmlvm.tutorial.ios.helloworld.portrait.HelloWorld", "didFinishLaunchingWithOptions", "?" ) XMLVMElem _r0; XMLVMElem _r1; XMLVMElem _r2; XMLVMElem _r3; XMLVMElem _r4; XMLVMElem _r5; XMLVMElem _r6; XMLVMElem _r7; _r5.o = me; _r6.o = n1; _r7.o = n2; _r4.i = 0; _r0.o = org_xmlvm_iphone_UIScreen_mainScreen__(); XMLVM_CHECK_NPE(0) _r0.o = org_xmlvm_iphone_UIScreen_getApplicationFrame__(_r0.o); _r1.o = __NEW_org_xmlvm_iphone_UIWindow(); XMLVM_CHECK_NPE(1) ...Copy the code

In my opinion, this scheme is rather unreliable, in case the generated code has a problem, basically can not be modified, also can not debug the code, so it is not recommended.

summary

Although this approach is less risky, I don’t think there is much code to share for many small apps, because most of these apps are developed around the UI, and most of the code is coupled to the UI, so there is not much in common.

Of all the concrete solutions currently available, only J2objC can be tried, and the others are immature.

Compile flow

Compilation streams go one step further than previous code conversions by directly compiling a language into a normal platform binary, which has obvious advantages and disadvantages:

  • advantages
    • You can reuse some code that is very complex to implement, such as a game engine previously implemented in C++, which is too expensive to rewrite
    • The compiled code is difficult to decompile
    • Maybe the performance will be better (depending on the implementation)
  • disadvantages
    • If the tool itself has bugs or performance problems, locating and fixing them can be costly
    • The compiled volume is not trivial, especially if you want to support ARMv8 and x86

Next we introduce the various schemes of this genre by distinguishing between the different languages.

C + + class

C++ is the most common choice, as C++ development is currently supported on Android, iOS, and Windows Phone. It is usually done in one of three ways:

  • Using only C++ to implement non-interface parts is the official preferred solution, which is currently used in many applications such as Mailbox and Microsoft Office.
  • Using 2D graphics libraries to draw your own interface is a common practice on the desktop, where many interfaces have personalization requirements, but is not used much on mobile.
  • Using OpenGL to draw interfaces is common in games.

Using C++ to implement non-interface parts is common, so I won’t repeat it here. In addition to improving performance and sharing code, some people use this method to hide key code (such as keys). If you don’t know how to build such a cross-platform project, check out Dropbox’s libmx3 project. It also has json and SQLite libraries embedded, and supports simple HTTP, EventLoop, and thread creation by calling system libraries.

If you want to implement the interface in C++, you can use objective-c ++ and C++/CX supersets of C++ on iOS and Windows Phone respectively, so it is relatively easy, but the problem is more troublesome on Android. The main reason is that the Android interface is mostly implemented in Java, so the biggest challenge of developing an interface in C++ is how to support Android. There are two ways to do this: call Java methods provided by the system through JNI or draw the UI yourself.

The first is possible, but the code is too redundant. For example, a simple function call requires so much code:

JNIEnv* env;
jclass testClass = (*env)->FindClass(env, "com/your/package/name/Test"); // get Class
jmethodID constructor = (*env)->GetMethodID(env, cls, "", "()V");
jobject testObject = (*env)->NewObject(env, testClass, constructor);
methodID callFromCpp = (*env)->GetMethodID(env, testClass, "callFromCpp", "()V"); //get methodid
(*env)->CallVoidMethod(env, testObject, callFromCpp);
Copy the code

Would it be easier to draw your own UI? For example, JUCE and QT are drawn by themselves. Let’s look at the effect of QT:

Looks pretty good, doesn’t it? On Android 5, however, many of the effects are missing, such as the lack of ripple effects and even the lack of borders. The fundamental reason is that it is modeled using Qt Quick Controls custom styles instead of using UI components. Therefore, it can not enjoy the system upgrade automatically bring interface optimization, can only be realized again, the workload is not small.

If you start with Android native components, you don’t need to do anything, and you can use the new AppCompat library to implement Material Design under Android 5.

The last option is to use OpenGL to draw the interface, and since EGL+OpenGL is inherently cross-platform, it is very convenient to implement it, as most cross-platform games currently do at the bottom.

Now that you can use OpenGL to develop cross-platform games, can you use it to implement interfaces? Of course it works, and the Android 4 interface is based on OpenGL, but it’s not just an OpenGL API, which is not practical, because the OpenGL API wasn’t designed to draw 2D graphics, so there’s no direct way to draw a circle, So in Android 4, Skia is used to convert paths into arrays of locations or textures, which are then rendered by OpenGL.

However, it takes a lot of work to fully implement Android’s UI architecture. Here is some of the code involved:

The path Lines of code
frameworks/base/core/java/android/widget/ 65622
frameworks/base/core/java/android/view/ 49150
frameworks/base/libs/hwui/ 16375
frameworks/base/graphics/java/android/graphics/ 18197

The text rendering alone is quite complicated and if you think it’s easy then you probably haven’t seen the world getting big. Maybe you know Chinese has coding issues and English has hyphen braces. But do you know that traditional Chinese has vertical typeset, Arabic is right to left, Japanese has hiragana script (listビ), Indian has vowels attached to the script (abugida አቡጊዳ)… ?

Compared if each platform development interface alone, seems to be a big workload, but at the moment, in each platform will have a good official support, tools and documentation are very perfect, so the cost is not so high, and can give the user and the system style consistent good experience, so I think that for most applications their UI is uneconomic.

In addition to more flexible control, it can also unify the style of different platforms. This is common in desktop applications. For example, under Windows, you will find that almost every required application has a different UI, and many of them have a skin change function. In this case, it’s good to draw your own UI.

Xamarin

Xamarin, which can be used to develop Android and iOS applications in C#, was developed from Mono and seems to be doing well commercially, with sound tools and documentation.

Because it is compiled into binary files in the way of AOT in iOS, it is classified into the compilation flow for discussion. In fact, it is implemented in The Android embedded Mono virtual machine, so it needs to install a 17M running environment.

On the UI side, it can use the system’s built-in interface components by calling system apis, or develop custom cross-platform UIs based on Xamarin.Forms that are not demanding.

For teams familiar with C#, this seems to be a very good solution, but the biggest problem with this solution is the lack of relevant information, and it is possible to find a solution when encountering problems. However, due to the lack of time, I have not studied it carefully, so I recommend reading this article, which talks about its advantages and disadvantages:

  • advantages
    • You have all the basic functions you need to develop an app
    • There is commercial support, and this project is good for Windows Phone, and Microsoft will support it
  • disadvantages
    • If you dig deeper, you find that features are missing, especially custom UI, because it’s not open source and you don’t know how to fix it
    • Xamarin itself has some bugs
    • There are not as many third-party libraries as there are on the native platform
    • Xamarin Studio is a far cry from Xcode and Android Studio in terms of functionality

Objective-c is compiled for Windows Phone

Microsoft knew its Windows Phone was too far from mainstream, so it wisely introduced a tool for compiling Objective-C projects to run on Windows Phone. There is little information about this tool, but given Visual Studio’s support for Clang, So most likely it will be compiled using the Clang front end, and the biggest benefit is that it will be easier to support Swift in the future, so I fall into the compilation stream.

For Android support, Microsoft should be using virtual machines, so it will be covered in the next section.

RoboVM

RoboVM can compile Java bytecode to machine code that can run under iOS, which is similar to GCJ, but it is implemented by first using Soot to compile bytecode to LLVM IR, and then compile it into binary files under different platforms by LLVM compiler.

For example, a simple new UITextField(new CGRect(44, 32, 232, 31)) will change to the following machine code (x86) :

call imp___jump_table__[j]org.robovm.apple.uikit.UITextField[allocator][clinit]
mov esi, eax
mov dword [ss:esp], ebx
call imp___jump_table__[j]org.robovm.apple.coregraphics.CGRect[allocator][clinit]
mov edi, eax
mov dword [ss:esp+0x4], edi
mov dword [ss:esp], ebx
mov dword [ss:esp+0xc], 0x40460000
...
Copy the code

The benefit of bytecodes-based compilation is that it supports a variety of languages built on the JVM, such as Scala, Kotlin, Clojure, and so on.

In terms of the runtime environment, it uses the same GC as GCJ, Boehm GC, which is a conservative GC and has a memory leak problem, although officially it has been optimized and the impact is not significant.

In terms of UI support, it is similar to Xamarin in that you can create interfaces directly from Java by calling system interfaces (Interface Builder support recently), as shown in the example above. It also boasts JavaFX, which will allow you to use the same UI on iOS and Android, but that seems a bit shaky at the moment.

In my opinion, the biggest use of RoboVM right now is developing games using libGDX. While it’s not nearly as powerful as cocos2d-x (especially for scene and object management), Java is still a lot more convenient than C++ (don’t tell me nobody makes games in Java, Minecraft is $2.5 billion), but this article will focus on UI development, so I won’t go into that,

RoboVM is similar to Xamarin, but RoboVM is less risky because it just needs to support iOS well, which is good for teams that prioritise Android versions, but there is little official documentation and it is unclear how well RoboVM will perform and stabilize on iOS.

Swift – Apportable/Silver

Apportable can compile Swift/Objective-C directly to machine code, but its official website is full of games, so using this as an APP feels like a bad idea.

So it came up with a tool called Tengu for APP development, which was a little bit more flexible than the previous one, essentially a little bit like the C++ common library, but Swift/Objective-C, Use Swift/Objective-C to compile and generate cross-platform SO files for Android calls.

Silver, which has yet to be released, supports not only Swift but also C# and its own Oxygene language (which looks like Pascal). In terms of interface, it also has a cross-platform non-ui library called Sugar, which currently has a Star count of 17. It’s so out of the mainstream that I can’t be bothered to study it.

It is possible to use Swift to compile SO for Android, but the relevant tools are not mature, SO it is not recommended.

Go

Go is a hot back-end service development language in recent years. It has simple syntax and high performance, and has many users in China at present.

Go has been available for Android since version 1.4 (and will be available for iOS in version 1.5), but only a few apis like OpenGL have been called before, so it was only used for game development, but it doesn’t feel right to me. Who else is developing games directly on OpenGL? Most games are based on a framework, and Go is so lacking in this area that I only saw a desktop Azul3D and it was very immature.

Because the View layer of Android is written entirely based on Java, it is inevitable to call Java code to write UI with Go, and there is no easy way to do this. At present, Go can only call external code using CGO, and then call JNI through CGO. This requires a lot of intermediate code, so currently Go 1.4 uses a rPC-like approach to do this. Examples from its source code show how cumbersome this approach is, and there must be a considerable loss of performance.

Moreover, the implementation of CGO itself has a performance penalty. In addition to calls to various irrelevant functions, it also locks up a Go system thread, which can affect other Gorountine operations, or even cause all Gorountine waits if too many external calls are made at once.

The root cause of this problem is that the Go stack is automatically extensible, which makes it easy to create countless Gorountine, but also makes it impossible to call c-compiled functions directly, requiring stack switching.

So using Go to develop cross-platform mobile apps is not currently feasible.

Rust does not have the performance of Go, and there is no performance penalty for calling C functions. However, there is no official support for iOS/Android yet, although there have been attempts to do so, it is not yet stable. It’s a good alternative to C++ for cross-platform common code, but it has the disadvantage of a complex syntax that scares off many developers.

Xojo

I thought BASIC was dead until Xojo, which uses BASIC, has a powerful looking IDE that feels like VisualBasic.

It should be targeted at kids or amateur developers, because it seems to be cheap to learn, but I don’t think so, because there are fewer people using it, and there are fewer online materials, so I’m afraid the cost will be higher.

Because of time and lack of love for BASIC, I didn’t study it much.

summary

From what we’ve analyzed so far, C++ is the safe choice, but it requires team members. If no one has written C++ before, try Xamrin or RoboVM.

The virtual machine flow

In addition to compiling binaries for different platforms, another common practice is to use virtual machines to support cross-platform execution. For example, JavaScript and Lua are both inherently embedded languages, so many solutions in this genre use both languages.

However, the virtual machine flow will encounter two problems: one is performance loss, and the other is that the virtual machine itself will take up a large volume.

Java is

When it comes to cross-platform virtual machines, Java comes to mind, because the language was designed to be cross-platform from the very beginning. Sun’s J2ME came out in 1998, and many small games were developed based on J2ME on mobile phones before the iPhone came out. It runs on Raspberry Pi.

As mentioned earlier, Microsoft provides a tool to compile Objective-C and run it on Windows Phone. I haven’t found detailed information on Android support, so I temporarily think it is a virtual machine approach. From the introduction of Astoria project, it is very well done. It not only supports C++ in NDK, but also implements Java debug interface, making it possible to debug directly with Android Studio and other ides. The whole development experience is almost the same as that on Android phones.

BlackBerry 10 also has built-in virtual machines to run Android apps directly, but it’s said to be a bit clunky.

However, as mentioned above, both C# and Java programs on iOS are implemented by AOT. So far, there is no program with Java virtual machine. I think the main reason is the limitation of iOS, ordinary app cannot call mmap and mprotect. If iOS is open, maybe one day someone will build a virtual machine like Microsoft that can run Android applications directly on iOS. No need for cross-platform development, everyone will just learn Android development.

Titanium/Hyperloop

Titanium is one of the most popular cross-platform solutions around the same time as PhoneGap. The biggest differences are: Instead of using HTML/CSS, it designed a set of Alloy, an XML-based UI framework, with code similar to the following:

app/styles/index.tss
".container": {
  backgroundColor:"white"
},
// This is applied to all Labels in the view
"Label": {
  width: Ti.UI.SIZE,
  height: Ti.UI.SIZE,
  color: "#000", // black
  transform: Alloy.Globals.rotateLeft // value is defined in the alloy.js file
},
// This is only applied to an element with the id attribute assigned to "label"
"#label": {
  color: "#999" /* gray */
}

app/views/index.xml

   class="container">
     id="label" onClick="doClick">Hello, World
  

Copy the code

Since CSS is so flexible that it slows down browser performance, would it make more sense to build your own UI mechanism? While there are performance benefits, there are learning costs associated with doing this, simple interfaces are not a problem, and once you start customizing, you’ll find that there’s too little information to go around.

Titanium also provides a cross-platform API for easy calls, which is more of a plus than a minus, especially with three issues:

  1. The API is limited, because it’s provided by Titanium, and it’s definitely less than the official API and has a lag that Titanium can’t keep up with
  2. Related information and community is limited, compared to Android/iOS is far from where to find the answer to the question
  3. Lack of third-party libraries. They certainly don’t have a version for Titanium, so you have to package whatever you use

Titanium is aware of this problem and is currently working on a next-generation solution called Hyperloop, which compiles JavaScript to native code. This has the advantage of making it easier to call native apis, such as those written on iOS

@import("UIKit");
@import("CoreGraphics");
var view = new UIView();
view.frame = CGRectMake(0, 0, 100, 100);
Copy the code

This solution is very similar to Xamarin, which basically translates Objective-C into JavaScript, meaning you can develop against Apple’s official documentation, But if you find some Objective-C syntax and you don’t know how to write it in JavaScript, you have to figure it out.

However, according to the submission history on Github, this project has been under development for nearly two years, but it is still in the experimental stage. According to the update frequency, only 8 times have been submitted in the last year, so I am afraid that it will be abandoned, which is very unreliable.

Therefore, I think Titanium/Hyperloop are very unreliable and not recommended.

NativeScript

For example, NativeScript recently introduced a tool that automatically generates the Wrapper API, in line with the system API.

With a tool that automatically generates wrappers, it is easy to develop cross-platform components based on the system API. Take a simple Button as an example. The source code is in cross-platform-modules/ UI/Button. This is how it works on Android (TypeScript leaves out a lot of code)

export class Button extends common.Button { private _android: android.widget.Button; private _isPressed: boolean; public _createUI() { var that = new WeakRef(this); this._android = new android.widget.Button(this._context); this._android.setOnClickListener(new android.view.View.OnClickListener({ get owner() { return that.get(); }, onClick: function (v) { if (this.owner) { this.owner._emit(common.knownEvents.tap); }}})); }}Copy the code

And this is how it works on iOS (a lot of code is omitted)

export class Button extends common.Button { private _ios: UIButton; private _tapHandler: NSObject; private _stateChangedHandler: stateChanged.ControlStateChangeListener; constructor() { super(); this._ios = UIButton.buttonWithType(UIButtonType.UIButtonTypeSystem); this._tapHandler = TapHandlerImpl.new().initWithOwner(this); this._ios.addTargetActionForControlEvents(this._tapHandler, "tap", UIControlEvents.UIControlEventTouchUpInside); this._stateChangedHandler = new stateChanged.ControlStateChangeListener(this._ios, (s: string) => { this._goToVisualState(s); }); } get ios(): UIButton { return this._ios; }}Copy the code

It can be seen that the usage is the same as the call method in the official SDK, but the language is changed to JavaScript, and the writing method looks strange. The style is similar to the previous Hyperloop, so there are also syntax conversion problems.

The biggest advantage of this is that it supports all system apis and third-party libraries, but the biggest disadvantage is that the generated file size is too large. Even if you do nothing, the generated APK file is 8.4MB, because it generates all API binding. This also makes it slow to open for the first time on Android.

In terms of the underlying implementation, NativeScript has V8 embedded in Android and its own compiled JavaScriptCore embedded in iOS (meaning no JIT optimization, for the reasons mentioned earlier), which has the benefit of calling lower-level apis. It also avoids the problem of JS engine inconsistency between operating system versions, but the result is larger generated file size and worse performance on iOS than WKWebView.

WKWebView is implemented on a multi-process basis, it is in the iOS whitelist, so it supports JIT.

It works well, with one-click compilation and run, and MVVM support for bidirectional data binding.

In my opinion, one of the big disadvantages of Both NativeScript and Titanium is that they are so exclusive that if you want to use them, you have to build on them completely, you can’t try them out in certain views, and there’s no support for embedding third party views directly. Is there a good solution to these two problems? There is, and that’s React Native.

React Native

React Native has a lot of discussion online, and there are a lot of answers on Zhihu. Although some of the answers are inaccurate from an underlying implementation perspective, most of the key points are covered.

Since I don’t like to repeat what others have said, here’s something else.

React Native’s idea is simply to use the platform’s built-in UI components on different platforms. This idea is not new, as SWT did more than a decade ago.

In terms of team, many members of Facebook’s iOS team are from Apple. For example, the manager of the Paper team and many of its members are from Apple. Because iOS is not open source, developers from Apple still have advantages. For example, Duet, a former Apple developer, killed every other solution on the market, and given Facebook’s open source project on iOS, their experience and technology on iOS is pretty good, so it’s not too bad from a team perspective.

React Native is an objective-C ++ framework for ComponentKit. Here is a code example for ComponentKit:

@implementation ArticleComponent

+ (instancetype)newWithArticle:(ArticleModel *)article
{
  return [super newWithComponent:
          [CKStackLayoutComponent
           newWithView:{}
           size:{}
           style:{
             .direction = CKStackLayoutDirectionVertical,
           }
           children:{
             {[HeaderComponent newWithArticle:article]},
             {[MessageComponent newWithMessage:article.message]},
             {[FooterComponent newWithFooter:article.footer]},
           }];
}

@end
Copy the code

It’s much less readable than XML in JSX, and with Swift adoption, this objective-C ++ based solution will probably become obsolete in a few years, so Facebook was right to bet on React.

I’ve seen people talk about Facebook going back to H5, but React Native doesn’t have much to do with the Web. The Web I understand to mean W3C specifications like HTML, CSS, DOM, React Native uses CSS Flexbox, navigator, XMLHttpRequest and other simple apis, not to mention the lack of openness of the Web. React Native is not the same thing as HTML 5.

The React Native iOS version of Facebook Groups is largely based on React Native. It uses a number of built-in components, such as ReactGraphQL, which IS a syntax for structured data queries. It is just like the query syntax of MongoDB to query JSON data, but it is not a document database, but only an intermediate layer. The specific data source can connect to other databases. It wants to replace the simple HTTP protocol of the front and back end like RESTful, so that the front end can obtain data more conveniently. It’s said to be open source (looks like it’s going to be implemented with Node).

The problem with taking too long to write is that a lot of things happen during this period. For example, GraphQL was not known when I started writing, so I needed to gossip about it. Now it’s officially announced, but there’s no mention of the Node implementation that I mentioned, which is still being quietly developed

React Native’s official video states that it can implement in-app updates, which Is actually forbidden by Apple (2.7 in App Store Review Guidelines), so keep it low-key.

Someone mentioned in the comments that Apple changed the terms of iOS 8.2 to allow JavaScript to be downloaded and executed, and that the authors of UIKit liked React Native

What I like about React Native is that it uses Flow. It supports defining function parameter types, which greatly improves code readability. It also uses ES6 syntax, such as the class keyword.

React Native is much cheaper to learn than traditional Objective-C and UIView, and developers familiar with JavaScript should be able to write a standard UI in half a day. It’s also much easier to draw an XML+CSS interface than a UIView with a Frame layout (I’ve never used Storyboards, it looks intuitive, but multiple editors can be very conflicting). If you’re interested, take a look at this detailed tutorial and try it yourself. Command + R updating code feels magical.

There are already over 500 repositories on Github, including sqLite, Camera and other Native components. With the improvement of these third-party components, React Native development requires less and less Native code.

The bad news is that React Native will have to wait half a year for the Android version, which is understandable, because the problem is much more complicated on Android, with Dalvik/ART in the way, making interaction very difficult.

NativeScript and React Native are very different in focus, making the two products currently heading in different directions:

  • React Native is designed to solve the problem of development efficiency. It does not expect to completely replace Native development. Its rootView inherits from UIView, so it can be used in some views, which is easy to mix and mix, without rewriting the entire app. You also need to explicitly expose the API to JavaScript when mixing
  • Like Titanium, NativeScript tries to develop entirely in JavaScript, exposing all the system apis to JavaScript, allowing JavaScript to have all the capabilities of a Native language by default. Then build on the basics again

I think React Native will definitely beat NativeScript because it’s much less risky to use. You can always experiment with parts of a View using React Native. If you have a problem, you can switch back to Native implementation. The risk is manageable, but NativeScript is not. This causes people to be afraid to use NativeScript when selecting the technology.

When the Angular team saw React Native, they started redesigning the Angular 2 presentation architecture to separate the Render layer from the existing one, making it easier to adapt to different runtime environments like React. Can run on NativeScript.

Overall, I think React Native is worth trying, and the risk is not high.

Scripts in the game engine

Most game engines are cross-platform, and in order to improve development efficiency, many have built-in scripting support, such as:

  • Ejecta, which implements the Canvas and Audio apis and can develop simple games, does not currently support Android
  • CocoonJS implements the WebGL API and can run games written by three.js
  • Unreal Engine 3 can be developed using UnrealScript, a language whose syntax is similar to Java
  • Cocos2d-js, the JavaScript binding of cocos2D-x, which uses the JavaScript engine SpiderMonkey internally
  • Unity 3D, you can use C# or JavaScript to develop game logic
  • Corona, developed using Lua
  • .

Cocos2d-js is said to be ok. Some small games are using it. Corona feels a little bit out of the mainstream. The biggest benefit so far seems to be the small size of the virtual machine. The embedded version is officially only 1.4m, which is the big advantage of the Lua engine.

Ejecta doesn’t support Android yet, CocoonJS has moved to a Crosswalk-like WebView solution, and UnrealScript is no longer supported in Unreal Engine 4. Instead, it moved to C++, and you’ll be interested to see Epic’s founder explain why.

Of course, these game engines are not suitable for making apps. On the one hand, they will encounter the interface drawing problems mentioned above. On the other hand, the implementation of game engines generally needs to be redrawn constantly, which definitely consumes more power than ordinary apps and is easy to be deleted after being discovered by users.

Adobe AIR

From what I’ve seen around me, almost everyone thinks Flash has given up on mobile, and I have to say that Adobe’s campaign is a misstep. Flash will still run on iOS even though it’s just giving up on mobile browsers. For familiar ActionScript team, it is a quite good cross-platform game development solution, the domestic game companies before useful, now there is no one I don’t know, but considering the many unknown the truth of children thought Flash hung up on the mobile end, so a serious shortage of reserve force must, even more people, Don’t think about anything else.

Someone in the comments pointed out that this is done by compilation on iOS and looks very similar to Xamarin RoboVM.

However, it also lacks good UI library for APP development. Flex has poor user experience. Currently only Feathers is still available, but it is mainly designed for game UI, which is not suitable for APP development.

Dart

Dart basically failed on the Web, so it moved on to mobile development. There are two ideas, one is an embedded language like Lua to unify common code, but since the Dart virtual machine is derived from V8, it was designed with just the JIT and no interpreter, not even bytecode. So it didn’t run on iOS, so the Dart team created a tiny Fletch virtual machine that runs on traditional bytecode interpretation execution and is as lightweight as Lua at just over 1W lines of code.

The other one is Sky, which is very popular recently. Here is a joke about the media at home and abroad. I have seen reports that Google wants to replace Java development under Android with Dart. It’s true that Google’s Chrome team developed this thing, but Google is a big company, ok? There are a lot of small teams, and a small team doesn’t represent Google. If it’s really Google’s decision, It will be introduced at the Google I/O keynote, rather than a less mainstream technology sharing like the Dart Developer Summit.

It has been reported that Sky only supports online applications, not offline, which is too wrong, they just want to demonstrate its online update ability, you want to embed the code in the APP of course can.

Sky’s architecture, shown below, takes cues from Chrome and relies on a messaging system to communicate with the local environment, making Dart code platform-independent and running on a variety of platforms.

If you read the previous article, you must be as concerned as I am about the question: How is Sky’s UI drawn? Use the system or draw your own? When I first watched Sky’s introductory video, I thought it was based on Chrome, because the speaker in this video is Eric Seidel, who is a very famous developer of WebKit project. He developed WebKit at Apple in the early years, In 2008, HE jumped to Chrome team, but he did not mention WebView in his speech, and the interface in the demonstration was very similar to the Native Material Design effect (such as the ripple effect when clicking), so I thought it used the Native UI like React Native.

However, when I downloaded the app and analyzed it, it didn’t use either Chrome/WebView or native UI components, was it painted by itself?

From the Sky SDK code, it has a lot of traces of Web, such as support standard CSS, a lot of DOM API, but its compiled volume is very small, libsky_shell. So is only 8.7 MB, I tried to simplify the Chrome kernel before. It also takes 22 MB to remove the WebRTC and other peripheral features, which is a small amount of space to remove core Web features such as SVG and some CSS3, so I suspect it does a simpler version of Chrome kernel rendering.

Mojo is not just a messaging system, it is a simple Chrome kernel! Using CLOC statistics code is exposed:

   12508 text files.
   11973 unique files.
    2299 files ignored.
-----------------------------------------------------------
Language              files     blank   comment      code
-----------------------------------------------------------
C++                    3485    129830    107745    689089
C/C++ Header           3569     92435    125742    417655
C                       266     37462     63659    269220
...
Copy the code

There are 70w lines of code in C++ without comments, and the directory structure is very Chromium style, at least in terms of technical difficulty, which confirms my previous statement that a simplified version of CSS/HTML can solve performance problems very well.

It also made me understand why Eric was so vague about Mojo, giving people the impression that it was just a messaging system, and what a big mistake it would have been to say that it was a striptease of Chrome. Google Announces Next-generation browser kernel to replace Blink.

Dart decided not to put the Dart VM in Chrome, not because it was rejected by the public, but because it forked Chrome to play with.

In general, the two Dart schemes are very immature. Although Sky is technically powerful, Dart language has a low acceptance rate. Compared with its cross-platform advantages, it has more disadvantages, such as the inability to use third-party Native UI library or third-party Web UI library. As a result, it will be very difficult for Sky’s community to develop, and it is destined to be non-mainstream. It is a pity for these technology giants, but direction is more important than effort. I hope they can wake up as soon as possible and let Sky also support JavaScript.

My conclusion

See here estimate many readers dizzy, there are so many kinds of programs, which in the end suits oneself most? Which one to study? Here is my brief opinion.

If you only know JavaScript, the best solution is React Native. With React Native, you can write a lot of small and medium applications even if you don’t know Native development. It’s probably not going to catch on anyway, so there’s no point in spending too much effort.

If you only know Java, try RoboVM or J2objC, which is more stable and reliable right now, but it can’t be developed entirely in Java like RoboVM, so you have to learn Objective-C to write interfaces, The downside of RoboVM is that it doesn’t seem to be stable and doesn’t seem to be used for anything other than games, which is bound to be more problematic than J2OBJC, so be prepared to step on the wrong foot.

If you only know C#, your only choice is Xamarin.

If you only know Objective-C, it’s a shame and there’s no proven solution, I suggest you learn Java, it doesn’t hurt to learn another language.

If you only know C++, you can do games or non-ui public parts. I don’t recommend using QT or drawing your own interface. Learn Native development instead.

If you only know Go, don’t expect to use it for mobile, because the current implementation is inefficient and tied to the underlying implementation mechanism of Go makes it difficult to optimize, so it’s not expected to change for a long time.

If you Rust, you enjoy doing things and probably know all the previous languages, so make your own decisions…

Of course, all of the above are personal, but for teams, don’t think about it. Use Native, and mix it with embedded solutions like Lua and React Native. Don’t use exclusive solutions like Titanium.

There are many technical points involved in this paper. If there are any inaccuracies, please feel free to put forward them. In addition, you can follow my microblog weibo.com/nwind for communication.

P.s. In this paper, said the mobile terminal, a lot of people think cross-platform never wonky, yes, that’s Web, but in fact the one of the most successful in history, too successful, that everybody used to it under the tree, nothing grows, it crowd out other solutions of living space, more than a decade ago and B/S and C/S fight?