Onsen UIは、最初からハイブリッドモバイルアプリケーション用に作られたため、Cordovaと組み合わせた場合の実装がなされています。そこで、今回はアプリを起動したときの最初の処理であるons.readyについて調べてみました。
Cordovaの初期化処理とdevicereadyイベント
そもそも、Cordovaの場合、cordova.js
が読み込まれると、初期化処理がはじまります。初期化処理には、アプリのネイティブ部分(AndroidならJava、iOSならObjective-C)の初期化処理と、各種プラグインの初期化処理があり、それがすべて完了すると、devicereadyイベントが発火します。
cordova-jsのソースコードは
https://github.com/apache/cordova-js
にありますが、この中でcommon/initモジュール
https://github.com/apache/cordova-js/blob/master/src/common/init.js
が、初期化処理を担う部分です。そして、このコードの一番下の方に、
channel.join(function() {
require('cordova').fireDocumentEvent('deviceready');
}, channel.deviceReadyChannelsArray);
とあります。ここでdevicereadyを発火していたんですね。ちなみに、channel.deviceReadyChannlsArray
は、
[channel.onNativeReady, channel.onPluginsReady]
という、ネイティブの初期化処理とプラグインの初期化処理からなる配列です。
Onsen UIのons.readyメソッド
さて、Onsen UIの初期化処理は
https://github.com/OnsenUI/OnsenUI/blob/master/core/src/ons/ons.js
にコードがあります。最初の方でonsオブジェクトが定義されていきますが、その最後で
ons._readyLock = new DoorLock();
ons.platform.select((window.location.search.match(/platform=([\w-]+)/) || [])[1]);
waitDeviceReady();
というコードがあります。ここ定義されている_reayLock
というのが初期化完了したかどうかを判定するオブジェクトですね。そして、waitDeviceReady()
メソッドにより、Onsen UIの初期化が完了するまで待機に入ります。
Onsen UIの初期化が完了したかどうかを判定するためのメソッドとしてons.isReady()
というメソッドがありますが、その実装は、単に_readyLock
オブジェクトに問い合わせているだけです。_readyLock
オブジェクトがロックされいたら、まだ初期化が終わっていないことになります。
ons.isReady = () => {
return !ons._readyLock.isLocked();
};
では、waitDeviceReady()
はどのようになっているかというと、
function waitDeviceReady() {
const unlockDeviceReady = ons._readyLock.lock();
window.addEventListener('DOMContentLoaded', () => {
if (ons.isWebView()) {
window.document.addEventListener('deviceready', unlockDeviceReady, false);
} else {
unlockDeviceReady();
}
}, false);
}
これを見ると分かる様に、まずDOMContentLoaded
イベントを待ってから、
-
もしCordovaアプリなら(
ons.isWebView()
が真なら)、さらにdevicereadyイベントを待ち、その後unlockDeviceReady
で_readyLock
オブジェクトのロックを解除します。 -
もしCordovaアプリでないなら、ただちに
unlockDeviceReady
で_readyLock
オブジェクトのロックを解除します。
それでは肝心のons.ready
メソッド自体はどうなっているのでしょうか?
コードを見てみると
ons.ready = callback => {
if (ons.isReady()) {
callback();
} else {
ons._readyLock.waitUnlock(callback);
}
};
となっていました。すでに初期化処理が終わっていたらただちにcallback
を実行し、そうでないなら、waitUnlock
メソッドでcallback
を登録して、_readyLock
オブジェクトが解除された時にcallback
が実行されるように設定しています。
まとめ
ということで、Cordovaを組み込んだ時のons.ready
はCordovaのdevicereadyイベントを受け取って
から発火することがわかりました。ということは、もし何らかの原因で、Cordovaのdevicereadyイベントが発火しなかった場合(プラグインに問題があるなど)すると、ons.readyも同時に発火しなくなってしまいます。ons.readyイベントが発火しない場合は、Cordovaプラグインについても確認してみましょう。
また、waitDeviceReady
についてですが、DOMContentLoadedイベントで判定しているので、HTMLのソースコードは読み込みが完了していて、DOM操作もできる状態になっているのですが、アプリの最初のページをJQueryやAngularなどでレンダリングしている場合、それが終わっているとは限りません。というか、基本的に終わっていません。
このため、ons.ready
が終わったからといって、即、1ページ目が完全に表示されているわけではないので、イベントリスナーなどの処理をするには早い場合があります。ページごとの初期化処理は、init
イベントで実装するようにしましょう。