TitaniumのWebView内Javascript開発の効率化

  • 13
    いいね
  • 1
    コメント
この記事は最終更新日から1年以上が経過しています。

この記事は、Titanium mobile Advent Calendar 2012の24日目の記事です。

Titaniumでハイブリッドアプリ

去年あたりからUI部分はHTML5で構築しながらも端末の豊富な機能の利用できるハイブリッドアプリが一つのトレンドかと思います。

もちろんUIとネイティブ側どちらもJavascriptで開発できるTitaniumも充分その流れに乗る資格はあるでしょう。

しかしTitaniumのWebViewではJavascriptのエラーや動的なDOMの構造の把握が難しくお世辞にも開発環境として効率的とはいえません。

餅は餅屋

そもそもリモートサーバーとAjaxで通信するのもTitanium側にTi.App.fireEventでイベントを送るのもシリアライズされたデータの受け渡しという点では変わりがないはず。

だとすればTitanium側へのイベントの送受信をリモート(ローカル)サーバーで代用できれば貧弱なWebViewの代わりにブラウザを使って開発ができてみんなが幸せになれる、、、かも。

これを実現するためにTitanium側へfireEventの呼び出しをちょっと工夫してAjax通信のように

ajax.js
ajax({
    url: "http://~",
    params: {a: 'foo', b: 'bar'},
    success: function(data) { },
    error: function(data) { },
    complete: function(data) { }
});

レスポンスをコールバックで処理するようにしておくとイベントの送受信先としてサーバーとTitaniumを切り替えて開発することが簡単になりそうです。

Ajax風にTitanium.App.fireEventを呼び出す

実際にやってみましょう。やり方はいろいろあるかと思いますがここではTi.App.addEventListener()一回きりで使い捨てる方法をとってみます。

index.js
//他のリクエストを処理中かどうか
var isConnected = false;
_ajaxLikeRequest = function (attr) {
    var complete, error, fakeUrl, params, success, _callback;
    fakeUrl = attr.url || '';
    params = attr.params || {};
    success = attr.success || function () {};
    error = attr.error || function () {};
    complete = attr.complete || function () {};

    //Titanium側からレスポンスが帰ってきた時に呼び出されるコールバック
    //iOSではsetTimeoutでcallstackを断ち切らないとうまく動作してくれない。    
    _callback = function (data) {
        setTimeout(function () {
            //すぐにコールバックはunbind
            Ti.App.removeEventListener('response', _callback);
            if (data.status === 'success') {
                success(data);
            } else {
                error(data);
            }
            complete();
            isConnected = false;
        }, 0);
    };
    Ti.App.addEventListener('response', _callback);

    //Titanium側のグローバルイベントを呼び出す     
    Ti.App.fireEvent('dispatch', {
        fakeUrl: fakeUrl,
        params: params
    });
    isConnected = true;
};

WebView側からのEventを受信するネイティブ側はこのような感じになります。

app.js
//webViewが発信したグローバルイベントを受信してfakeUrlで振り分ける
_dispatch = function (e) {
    if (e.fakeUrl === 'ti/hello') {
        _fakeServerRequest(e.params);
    } else if (e.fakeUrl === 'ti/goodbye') {
        _fakeServerRequest(e.params);
    }
};

//処理後webViewにグローバルイベントでレスポンスを返す。
_responseToWebView = function (data) {
    Ti.App.fireEvent('response', {
        status: data.status,
        message: data.message
    });
};

Ti.App.addEventListener('dispatch', _dispatch);

実際の例はこちら
もしTi.App.fireEventでデータのシリアライズ方法を詳しく調べたい場合はこちら

また今回の例はWebView(HTML)側=>Titanium側へのイベントの受け渡しですが、逆方向やWebView以外のWindow間などでも同じように使えるかと思います。

ハイブリッドアプリをTitaniumで開発する上で今後調べておきたいこと

  1. mobilewebに関する日本語情報が少ない。今回のAdvent Calendar 2012でも取り上げる人がいなかった。
  2. AlloyがTitaniumerに一般化することでWebView内のJavascriptにもunderscore.jsでテンプレートを使うことが一般的になるか?
  3. SenchaやJquery mobileからナビゲーションなどを省いたもっと手軽なフレームワークがあってもよさそう。