Xamarin と React Native と Flutter の違いを正しく理解しよう

DroidKaigi2018 でもセッションがあった Flutter がβ版になりました。

* [グーグル、Android/iOS対応のUIフレームワーク「Flutter」ベータ版を公開 - CNET Japan](https://japan.cnet.com/article/35115358/)

これでまた、にわかにクロスプラットフォーム開発ツール(以下 "X-Plat Tool" と略)が盛り上がってる気がします。
Flutter が出たからと言って、Xamarin や React Native など、先行する様々な X-Plat Tools が死ぬわけでもなく、ただ選択肢が増えて嬉しいやら戸惑うやら、ということです。

ここでは、Flutter と、先行する React Native、Xamarin を(独断を交えて)比較して、それらの違いを見てみたいと思います。

## 共通化できる(とされる)プラットフォーム

X-Plat Tool がどのプラットフォームまでカバーするかを比べてみます。ツールそのものに加え、フレームワークや言語自体も含めた広範な考えです。

| Platform       | Xamarin/.NET | ReactNative/JavaScript | Flutter/Dart |
|:-----------------|:-------:|:------------:|:-------:|
| iOS                | :thumbsup: |  :thumbsup:  | :thumbsup: |
| Android            | :thumbsup: |  :thumbsup:  | :thumbsup: |
| デスクトップ(Windows)| :thumbsup: |              |         |
| デスクトップ(Mac)    | :thumbsup: |              |         |
| Web(フロントエンド)  |       |  :thumbsup:  | :thumbsup: |
| Web(バックエンド)    | :thumbsup: |  :thumbsup: | :thumbsup: |

概ね、デスクトップアプリに対応するか、Webアプリに対応するかで選択肢が大きく変わります。

## 開発者に提供される API

X-Plat Tool が開発者にどんな「API セット」を提供するかを比べてみましょう。
ここでは２つに分類してみます。

### A. 開発者は、X-Plat Tool の 独自API を利用する

この方式の X-Plat Tool は、それ専用のAPIセットを開発者に提供します。
例えば Flutter では ``Stack`` というレイアウトクラスを提供しますが、これは Android の ``FrameLayout`` に近いものと考えられます。
あるいは JSX や XAML などの DSL(Domain Specific Language) を使用する場合もあります。React Native では画面のデザインは JSX(return で HTML っぽいタグを返すアレ) を使用します。

* :no_good: 新たに API を学習する必要がある（＝プラットフォーム固有のAPI知識が活かせない）
* :no_good: プラットフォーム固有の機能を使用するには Kotlin や Swift などネイティブの開発言語をツールを使わなければならない(＝ **APIの相互運用性が低い** )
* :ok_woman: 複数のプラットフォームでコードを共通化できる(ｲﾏｻﾗﾅﾆｦｲｯﾃﾙﾝﾀﾞ)
* :no_good: "共通API" と言いながら iOS でしか(Android でしか)動作しないかも知れない[^5]

[^5]: Titanium Mobile はこれが多かったという印象が深く心に刻まれています。。。

### B. 開発者は、プラットフォーム固有の (薄いラッパー)API を利用する

こちらの方式は、プラットフォーム固有の API を、X-Plat Tool の言語でラップして提供します。Xamarin(Xamarin.Android)では、Android SDK の API が、ほとんどそのまま C# から呼び出せます。例えば Android SDK の ``android.location.LocationManager`` は、 Xamarin では ``Android.Locations.LocationManager`` として利用できます。

* :no_good: それ自体はコードの共通化にならない(言語の標準APIやフレームワークでしか共通化できない)
* :ok_woman: プラットフォーム固有のAPIが X-Plat Tool の言語からダイレクトに呼び出せる(＝ **APIの相互運用性が高い** )
* :ok_woman: (上記であることから)開発やデバッグが一つの環境でシームレスに行える

## できあがったアプリケーションのユーザーインターフェース

アプリのUIは、エンドユーザーの反応に最も影響するため、特に注意が必要です。
こちらも２つに分類しています。

### あ. ネイティブのUIパーツを利用する

この方式では、X-Plat Tool での UI定義は プラットフォーム固有の UIパーツ にマップされます。例えば React Native での ``<Text>`` タグは、Android では ``TextView`` 、iOS では ``UITextField`` が使用されます。

* :no_good: 複数のプラットフォームのUIパーツ群で、共通で存在する機能しか提供できない
* :ok_woman: エンドユーザーにネイティブの「忠実な」UIを提供できる
* :ok_woman: プラットフォーム固有OSSライブラリが比較的利用しやすい(基本的にはブリッジしてあげれば良い ＝ **UIパーツの相互運用性が高い**)

### い. X-Plat Tool が自力でUIパーツを描画する

こちらの方式は、ネイティブのUIパーツは使わず、X-Plat Tool が持つレンダリングエンジンを使用して自力でUIパーツを描画し、マウスやキーボードのイベントも自力でハンドリングして操作感を提供します。
（インターネット老人会の皆さまには「Adobe の Flash アプリだよ」とでも言えば伝わるかと思います。）

* :no_good: ネイティブのUIパーツと見た目や操作感が微妙に異なる(かも知れない)
* :no_good: ネイティブのUIに比べて動作がもっさりする(かも知れない)[^7]
* :no_good: プラットフォーム固有OSSライブラリが比較的利用しにくい(独自レンダリングエンジンの影響を考慮する必要がある ＝ **UIパーツの相互運用性が低い**)[^14]
* :ok_woman: 「スタイル」を切り替えるだけで画面の Look and Feel を変更できる
* :ok_woman: 複数のプラットフォームに「完全に同一のUI」を提供できる[^10]

[^7]: Flutter や DelphiXE(の FireMonkey) では GPU を利用した高速なレンダリングが可能になっているとのことです。
[^10]: https://twitter.com/najeira/status/968774727022948352 を見て、同じ理由で昔 Flash AIR を使ったのを思い出しました。
[^14]: https://twitter.com/najeira/status/969106318098223104 によると、現行の Flutter では実質行えない模様です。

## 比較表

結局、言語もIDEも含めてモバイルネイティブアプリを主対象とした X-Plat Tools の比較表を作ってしまった。。。

* Xamarin 
* React Native
* Flutter
* Titanium Mobile
* RubyMotion
* Qt 
* Delphi
* Adobe AIR
* NativeScript
* RoboVM
* Kotlin X-Plat(予想)

※ゲームエンジンやWebViewを使用するタイプの X-Plat Tools は、今回の比較軸とは変わってくると思うので載せていません（が、実際にはもちろんこれらも選択肢に加えるべきです）。

|        | Xamarin | ReactNative| Flutter | Titanium Mobile | RubyMotion | Qt | Delphi | Adobe Air | Native Script | RoboVM | Kotlin X-Plat(予想) |
|:-----------------|:-------:|:------------:|:-------:|:-------:|:-------:|:-------:|:-------:|:-------:|:-------:|:-------:|:-------:|
| (主な)提供者 | Microsoft |  Facebook  | Google | Appcelerator[^9] | Scratchwork | Qt Company | Embarcadero Technologies[^8] | Adobe | Progress Software | Xamarinが買収後死亡[^4] | JetBrains |
| 開発言語 | C# |  JavaScript  | Dart | JavaScript | Ruby | C++ | Object Pascal | Action Script | JavaScript | Java | Kotlin |
| (主な)開発環境 | Visual Studio |  As you like  | IntelliJ/VSCode[^12] | Titanium Studio | As you like | As you like | RAD Studio | Flash Builder | As you like | Eclipse | CLion[^13] |
| 対応Platform(言語含む) | iOS, Android, Win, Mac, Web(Back) | iOS, Android, Web(Front), Web(Back) | iOS, Android, Web(Front), Web(Back) | iOS, Android, Web(Front), Web(Back) | iOS, Android, Web(Back) | iOS, Android, Win, Mac, Web(Back) | iOS, Android, Win, Mac | iOS, Android, Win, Mac | iOS, Android, Web(Front), Web(Back) | iOS, Android, Win, Mac, Web(Back) | iOS, Android, Win, Mac, Web(Front), Web(Back) |
| 提供される API | B.薄いラッパーAPI + A.独自API[^6] |  A.独自API  | A.独自API | A.独自API | B.薄いラッパーAPI | A.独自API  | A.独自API + B.薄いラッパーAPI[^1] | A.独自API  | A.独自API + B.薄いラッパーAPI[^3]  | B.薄いラッパーAPI | B.薄いラッパーAPI |
| UIの提供方式 | あ.ネイティブ | あ.ネイティブ | い.独自 | あ.ネイティブ | あ.ネイティブ | あ.ネイティブ？[^2] | い.独自+あ.ネイティブ[^11] | い.独自 | あ.ネイティブ | あ.ネイティブ | あ.ネイティブ | 

[^1]: [Delphiならここまでできる︕ iOS / Androidネイティブアプリ構築術](https://img.en25.com/Web/Embarcadero/%7B4cb125b3-1fd8-45eb-a0be-8beffb7702a6%7D_dcamp33-T4.pdf) 参照。
[^2]: [エイリアンウィジェット](https://blog.qt.io/jp/2011/02/24/alien-widgets-on-mac/) と呼ばれるネイティブに依存しないViewも存在する模様。
[^3]: [NativeScript Documentation Chapter 6—Accessing Native APIs](https://docs.nativescript.org/angular/tutorial/ng-chapter-6) 参照。 
[^4]: https://github.com/robovm にリポジトリはある模様。
[^6]: Xamarin.Android, Xamarin.iOS などは 「B」、Xamarin.Forms というフレームワークは 「A」 に該当します。
[^8]: Embarcadero Technologies は IDERA に買収され、現在は小会社となっています。
[^9]: Appcelerator は Axway に買収され、現在は小会社となっています。
[^11]: [コメント](https://qiita.com/amay077/items/dff88e7ce6868615a9bb#comment-b01b9a057c67dc9dfa0f) より。指定によりネイティブに描画させることもできるとのことです。 
[^12]: [Get Started: Configure Editor - Flutter](https://flutter.io/get-started/editor/) では  IntelliJ と VS Code が紹介されています。
[^13]: [Kotlin/Native - Kotlin Programming Language](https://kotlinlang.org/docs/reference/native-overview.html) 

月並みなまとめですが、クロスプラットフォーム開発ツールを選択するには、

* ターゲットにするプラットフォーム
* 提供者の規模、サポート、継続性
* 開発言語や開発ツール vs チームメンバのスキルセット(あるいは習得容易性)

を評価し、さらに開発するアプリの性質に応じて、

* X-Plat Tool の標準機能で行えない機能がどのくらいあるか？
* X-Plat Tool の標準機能で行えない機能をどのように補完するか？(共通側で実装するか、ネイティブ側で実装するか、etc)

を検討することになると思います。
(もちろん X-Plat Tool を「採用しない」という選択肢も含めて。
あるいは Cordova のようなWebViewベースのX-Plat開発ツールもあれば、Unityのようなゲームエンジン系のX-Plat開発ツールも場合によっては候補になり得ます。)

例えば Flutter は美麗なアプリを迅速に開発できる、と謳われていますが、個人的には Webアプリプラットフォームの [kintone](https://kintone.cybozu.co.jp/jp/) をイメージさせます（筆者は kintone について、Flutter と同じく『美麗なWebアプリを迅速に開発できるツール』と(主観で)認識しています。対して Xamarin や React Native は Salesforce や SharePoint のように「なんでもできるが作るのはやや大変である」と相対的に思います）。
また Flutter について、「標準UIだけでなく凝ったUIも容易に実現できる」との[ご意見をいただきました](https://qiita.com/amay077/items/dff88e7ce6868615a9bb#comment-797c261e89cf45e10103)。
さらに、 React Native も、「Webの技術(CSSやAnimated API)でカスタムUIを用意に実現できる」との[ツイートがあります](https://twitter.com/Nkzn/status/1024488206916415488)。 
この記事は推測も多く含んでいるので、事実は、経験者・識者の方の情報を信じるのが一番です。

Kotlin Multi platform にはとても期待しています。うまく進化して流行ってくれれば、(現状での)モダンな言語で、プラットフォーム全方位な開発が実現できるんじゃないかなあ、と。

単純な比較表には現れない得意・不得意点もあるはずなので、日頃からアンテナ高く、できればたくさんつまみ食いしておきたいですね。

## 参考

* [DroidKaigi2018で発表したFlutterアプリの話のスライド補足 - Konifar's WIP](http://konifar.hatenablog.com/entry/2018/02/11/081031)
* [Android / iOS アプリの開発にクロスプラットフォームの Flutter を実戦投入した｜najeira｜note](https://note.mu/najeira/n/n8924408dd07b)
* React Native Androidはなぜ動くのか -  [DroidKaigi 2018で喋ってきました+α - ナカザンドットネット](http://blog.nkzn.info/entry/2018/02/09/230647)
* [Delphiならここまでできる︕iOS / Androidネイティブアプリ構築術](https://img.en25.com/Web/Embarcadero/%7B4cb125b3-1fd8-45eb-a0be-8beffb7702a6%7D_dcamp33-T4.pdf)
* [Xamarin.Android で始めるクロスプラットフォームモバイルアプリ開発](https://speakerdeck.com/amay077/xamarin-dot-android-teshi-merukurosuhuratutohuomumohairuahurikai-fa-number-droidkaigi-number-droidkaigi1)
* [Titanium 最近の動向 (2016年)](https://www.slideshare.net/tdtsh/titanium-2016)
* [Xamarin 使いが Kotlin のマルチプラットフォーム対応コードを読んだ感想 - Qiita](https://qiita.com/amay077/items/45b1ad4b9c5d3a03cf9c)