"モノを作るモノ"を作る会社です
2017.04.11

React Native と Android Studio を使い比べてみる

黒田 大介(Dycoon)です。仕事では少し入り組んだwebアプリのフロントエンドをJavaScriptで書いたり、Unityを触ったりしています。

今回は Smartphone でプラットフォームが用意している UI の機能を使うようなアプリ開発について調べてみます。Smartphoneのアプリ開発ではプラットフォームが用意している開発環境と、それらを間接的に扱う代替的な開発環境のどちらを使うかという選択肢があります。

基本的にはSmartphoneアプリ開発はOSのプラットフォームが用意している開発環境を利用すればおこなうことができます。

  • Android Studio + Android SDK + Java (あるいはKotlin等JVMを出力できる言語)
  • XCode + iOS SDK + (Objective-C or Swift)

これらを使う場合、プラットフォームが提供するAPIを余さず使うことができます。しかし、マルチプラットフォームの開発をおこないたい場合(共通化する害が少なそうな部分であっても)言語が違うことにより複数同じようなコードを書く必要が発生します。またAPIの違いをうまく扱う必要があります。

一方では直接扱わずできるだけ共通の言語およびAPIで開発できるフレームワークもいくつかあります。

  • OSのUI機能を使うもの
    • ReactNative
    • Xamarin
  • OSのUI機能を(あまり多くは)使わないもの
    • Cordova(WebViewによる動作)
    • ゲーム用だとUnityやcocos2d-xなども

ただ、こうしたフレームワークは必ずしもすべての処理を共通の言語や API で書くことができるわけではありません。フレームワークがカバーしていない部分はプラットフォームのAPIを結局操作しなければいけません。特にOSのUI機能を使用しないものはプラットフォームに備わっている機能を呼び出せる量が少ない傾向があります。また、あまり十分に使用や開発がされてないフレームワークだとバグが多く残っていたりすることもあります。

それでも共通の言語やAPIで書ける部分が多ければその分は開発コストを低減することができ、魅力的です。

また、私はJavaScriptやReact.jsなどはよく使うことがありますのでReactNativeやCordovaなどJavaScriptを利用できるフレームワークは学習コストも低そうです。

OSのUI機能を使うものの中でJavaScriptとReact.jsで書けるReactNativeとAndroid Studioで同じものを作ってみました。 そしてどういう違いがあるかなどを記しました。

例題の内容

  • pinterestのrssを読み込み画像をgrid状のレイアウトで並べる
  • Drawer layout
  • 設定画面で使いそうなUIを並べた画面を作る

スクリーンショット

React Native Androidによるアプリのスクリーンショット ReactNative Screen App Shot

React Native iOSによるアプリのスクリーンショット ReactNative iOS App Screen Shot

Android Studioによるアプリのスクリーンショット Android Studio App Screen Shot

実際に使ってみて気になった点

言語に関する違い

  • ReactNativeではJavaScript (ES2015)
  • Android StudioではJava

Android Studioを使用してみると IDE の機能でJavaやxmlなどで補完機能がよく働き使いやすいと思いました。特にJavaではCallbackなどは文字の量が多いので助かります。

ただ、Javaの言語自体には静的型推論の機能がないことなど少し不便に思うところもありました。言語として足りない部分はKotlinを使うと解決できる部分もあるかもしれません。

JavaScriptはテキストエディターで書いてもそれほど私は不便を感じませんが、静的型付き言語ではないので補完やリファクタリング、型関するテストなどの部分で場合によっては効率が悪いかもしれません。この点についてはTypeScriptで多少改善できるかもしれません。

React.js であることの良し悪し

React.jsはUIアプリケーションを記述する上でAndroid Studioよりも優れている部分がいくつかあると感じました。

例えばAndroid Studioではlayoutのidとかがアプリ全体でユニークでないといけません。これは扱わなければいけないUIの要素が多くなった場合問題が出てきそうで、少し気になります。React.jsだとそういったものは局所性を持って扱うことができます。

項目の表示などをおこなう際のテキストの指定はAndroidでは以下のとおりです。

<TextView
    android:text="Label"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:id="@+id/labelView"
    android:layout_gravity="left|center_vertical" />
TextView labelTextView = (TextView)getView().findViewById(R.id.labelView);
labelTextView.setText("label[left]");

JavaからViewの内容を変更する場合はユニークなidを指定する必要もあって、レイアウトを記述するxmlではlabelViewのidは他の場所では使えません。

ReactNativeではViewの指定はrenderメソッド内で例えば以下のようにおこないます

return (
  <View style={styles.itemLeft}>
      <Text>
          picker [{this.state.picker}]
      </Text>
  </View>
);

どういうテキストを表示するかは、表示の記述のところに直接書きます。Componentのメソッドを呼ぶ場合もrefの仕組みでグローバルなidを用意すること無く参照することができます。1

また、AndroidのActivityとFragment, Viewでライフサイクル等の考え方が若干一貫性がないように思います。その点ではReact.jsのComponentだと考え方が一貫しているのは扱いやすいです。ただ、Activityに関してはReact.jsのComponentの枠組みで扱えるわけではありません。

React Nativeでプラットフォームが変わったときのUIの再現性

私が触った範囲だとReactNativeではstatus bar付近のレイアウト関連がうまくOSの違い等を吸収できてないようです。サンプルコードでもiOSではstatus barの分の位置をずらすために20という固定値を使っているのが若干気になります。

const styles = StyleSheet.create({
  header: {
    /* snip */
    paddingTop: 20,
  },
  /* snip */
});

また、今回React Nativeで作ったAndroidアプリでは透明なstatus barは実現できておりません。 React NativeとAndroid Studioによるアプリのstatus barの違い

また、ReactNativeのpickerはiOSとAndroidで見た目が大きく違っており、そうしたことも気をつける必要がありそうです。実際に該当のプラットフォームで動かして確認してみるということは必要だと思いました。

良い Package はあるか?

例えばUIパッケージはどうか見比べてみました。Material UIの雰囲気を持つDrawer Layoutで使用したパッケージは以下のとおりです。

  • ReactNative
  • Android Studio
    • MaterialDrawer
      • Android Support LibraryだとAPI Level 15なのがAPI Level 14にできる
        • ただ、Facebook SDK とかは API Level 15 を必要とするのでこちらは使わなくていいかなという気もする
      • star 7143

第三者が配布しているパッケージを使用できれば工数が減らせる部分があります。しかしその一方で必ずしも安定して動作しないことあるので注意が必要です。たとえばReact Nativeのローディングアニメーションでreact-native-progressを試してみたところVector Graphics描画関係でアプリがクラッシュするバグに遭遇しました。

ユーザー数などを鑑みると現状だとAndroidのpackageの方が安定しているものが多いのかもしれません。ただ、MaterialDrawerを使った感想としては動的な変更がおこないにくいインターフェースなのが気になりました。MaterialDrawerが採用しているインターフェースは一般的なものでない気もします。しかし、UI Compoentをpackage配布する仕組みとしてはReact.jsの仕組みの方が扱いやすいかなという印象は持っています。

Debug 環境はどうか?

React NativeのJavaScriptのdebugについてはChrome DevToolsを使うことができますが、表示に関しては Debug はできないようです。AndroidのUIのデバッグするためのツールはありますがChrome DevToolsほど強力ではないようです。

そのため React Native はブラウザ上での開発ほどは楽では無いと思います。

通信関係に関して

Android StudioでAsyncTaskloaderを使用したときthreadを作りすぎてクラッシュしたことがありました。対策としては自分でキューイングして並列して読み込む数を制限するのが良いようです。クラッシュしなくなるだけでなく読み込み速度も向上するようです。

このようにthreadなど少し気をつけて扱ったほうが良い仕組みはAndroidだと結構露出しており気をつける必要がありそうです。ただ、picassoなど通信用のパッケージを利用することでより手軽な扱いができそうです。

ReactNativeでは第三者が配布しているパッケージを使うかプラットフォームに近い部分で自分で用意するなどしないとJavaScript の部分では Multithreading自体ができないため、安全な一方で制限もあります。

どちらを使うか?

ReactNativeとAndroid Studioを触り比べて見ました。ReactNativeの方が仕組みとしては優れていると感じることが多かったです。出来上がった物自体は安定して動いているように見えます。見た目やパフォーマンスの点でもそれほど遜色が無いようです。私は本格的に使ってみてもいいと思いました。

それでも、 Android Studioを触ったりある程度理解していたほうが問題が発生したときに対処しやすいことがありそうです。同じようにiOSを使う場合はXcodeも扱い慣れている方が良さそうです。

番外編:今回比較したもの以外のフレームワークとの違いについて

JavaScriptを使いたい場合Cordovaという選択肢もあります。CordovaではWebViewでUI の描画をおこなうので基本的にはHTMLで表示を作ります。Android 4.4 (API Version 19)より前のWebviewはかなりbuggyなのでそのバージョンで動くようにということだとReactNative (API Version 16以上で動作)の方が良い選択肢かもしれません。

(2017/04/27追記) 古いAndroidではCrossWalkを使えば安定して動きそうです。

Unity等ゲーム用のフレームワークの場合、消費電力が上がりがちらしいのが目的によっては問題かなと思います。

  1. Rect.jsのrefの例は以下を参照してください https://facebook.github.io/react/docs/refs-and-the-dom.html 

« React VR (WebVR)を試してみる
Back to blog list.
このエントリーをはてなブックマークに追加
follow us in feedly
Recently posts