前のページ次のページ上に戻るホーム SophiaFramework UNIVERSE 5.3

3.2. SFY アプリの全体的な処理の流れ

3.2.1. アプリの起動

SFY アプリの起動は、 SFC アプリと同様にブートローダ (SFCApplet::Boot 関数)によって行います。

[Note] 注意

SFCApplet::Boot 関数はアプリで最初に実行される関数です。

ブートローダーにより、 ファクトリ関数(helloworld::Factory 関数)が実行され、 アプリケーションクラスのインスタンスが作成されます。

これ以降、SFCApplication::Terminate 関数の呼び出し、 または電源キー(AVK_POWER)/クリアキー(AVK_CLR)の押下などによりアプリが終了するまで、 アプリは実行中であり、必要に応じて BREW イベントを処理します。

ブートローダ(SFCApplet::Boot 関数)とファクトリ関数(helloworld::Factory 関数)は、 以下のように実装します。

ブートローダ(SFCApplet::Boot 関数)には、 ライセンスコードを設定し、 引数 id が AEECLSID_HELLOWORLD であるときに helloworld アプリケーションクラスのインスタンスファクトリ関数 (helloworld::Factory 関数)を返す処理を記述します。

ファクトリ関数(helloworld::Factory 関数)には、 helloworld アプリケーションクラスのインスタンスを生成する処理を記述します。

[Tip] Tip

アプリケーションクラスのインスタンスは、 1 アプリにつき 1 つだけ生成します。

[Note] ClassID とライセンスコード

BREW 実機(BREW 移動機)では、 アプリの ClassID に対応した正規ライセンスコードを設定しなければアプリは起動しません。

開発時は Example / Tutorial フォルダ内にあるサンプルアプリの ClassID とライセンスコードをテスト用に使用してください

BREW シミュレータでは、ライセンスコードを設定しなくてもアプリは起動します。

参照: ライセンスコード

例 3.1. ブートローダとファクトリ関数

// 
//  helloworld.cpp
//

#include "helloworld.hpp"

// ブートローダ
SFCApplet::FactorySPP SFCApplet::Boot(AEECLSID id, SFXAnsiStringPtr license)
{
    // 実行ライセンスコードを設定する(実機の場合は必須。シミュレーターでは省略可)
    *license = "heap://"
               "TIXDRQXNU5WHU8Y3Z9WOHWQR6Z3VPSDHDV5CR1S4XASPWLUHWAS7Z5Z2TGS3XMSAT3UPUQTLTARCYPSF"
               "UEJZ6ROSJWGUQSEYKR6V2U4VESMTQLHKZ6X7Y2VKXHWIX3XBU0Z7VHWHXIZBSGT5SPU3XLX0Z1Y4R3TC"
               "U6WGT9WHWIVNYHYCUCR9T3SMTEWPRNVAX1Y4VPW2YCY9YQV5R7Z9UIVHT6SDUPU2SIW6VCRCWBR2S4WQ"
               "UPYFWCYGT4VIT1WHXGYPTQSFYPWNV3ULRNWFW7RBRFVKUKS2YQSQYHW1TPUPXBZ6UEY2WOYKR7S3TAU4"
               "TQS6UHVFVEVLU3R5SDSKW7RPTNTPVQU2T4R8Z4VLUGEW3U98TLDR8/";

    return (id == AEECLSID_HELLOWORLD) ? (&helloworld::Factory) : (null);
}

// ファクトリ関数
SFCInvokerPtr helloworld::Factory(Void)
{
    return ::new helloworld; // helloworld アプリケーションクラスのインスタンスを生成する
}

3.2.2. イベントループ

SFY アプリでは、 アプリ起動後(アプリケーションクラスのインスタンス生成後)、 BREW 環境からイベント(BREW イベント)を受信すると、 SFCApplication::Invoke 関数が呼び出されて以下の処理を行います (参照: SFCApplication::Invoke 関数の内部実装)。

  1. (登録されていれば)優先的イベントハンドラを呼び出します。
  2. SFEVT_APP_START / SFEVT_APP_RESUME イベントを受信したとき、 または優先的イベントハンドラが終了するとき、 優先的イベントハンドラが登録されていなければ、 SFYApplication::HandleRender 関数を呼び出して全画面 (デバイス画面とルート以下のレスポンダツリー)の再描画を行います。
  3. SFEVT_APP_START / SFEVT_APP_RESUME / SFEVT_APP_STOP / SFEVT_APP_SUSPEND イベントを受信したとき、 あるいは優先的イベントハンドラがイベントを処理しなかったとき、 SFYApplication::HandleEvent 関数を呼び出してイベント処理を行います。
  4. メモリ不足などの致命的エラーが発生したときは、 SFCApplication::HandleError 関数を呼び出してエラー処理を行います。
[Note] 優先的イベントハンドラについて

SFXEventBypass クラスの解説を参照してください。

例 3.2. SFCApplication::Invoke 関数の内部実装

/*private */Bool SFCApplication::Invoke(SFXEventConstRef event)
{
    Bool    overload(false); // イベントを重複して処理するかどうかを表すフラグ
    Bool    render(false);   // 全画面を再描画するかどうかを表すフラグ
    Bool    result(false);   // 処理がなされた場合、"true" が設定される

    switch (event.GetType()) {

        case SFEVT_APP_START:
        case SFEVT_APP_RESUME:
            // SFEVT_APP_START / SFEVT_APP_RESUME の場合

            render = true;   // 全画面を再描画する

        case SFEVT_APP_STOP:
        case SFEVT_APP_SUSPEND:
            // SFEVT_APP_START / SFEVT_APP_RESUME / SFEVT_APP_STOP / SFEVT_APP_SUSPEND の場合

            overload = true; // イベントを重複して処理する
            result = true;   // BREW の仕様では、これらのイベントには true を返す必要がある
            break;

        default:

            break;
    }

    if (_bypass != null) {   // 優先的イベントハンドラの処理

        // 優先的イベントハンドラを呼び出す
        result = (*_bypass)(event, _reference);
    }

    if (render) {  // アプリ開始/再開時と優先的イベントハンドラ終了時の全画面再描画

        if (IsRenderable()) {  // 優先的イベントハンドラが登録されていない場合

            // 全画面を再描画する
            HandleRender(event);
        }
    }

    if (!result || overload) {  
        // 優先的イベントハンドラで処理されなかったイベント、あるいは
        // SFEVT_APP_START / SFEVT_APP_RESUME / SFEVT_APP_STOP / SFEVT_APP_SUSPEND イベントの処理

        // イベントを処理する
        result = HandleEvent(event) || overload;
    }
    return result;
}// SFCApplication::Invoke //
[Caution] 注意

HandleEvent / HandleRender 関数については、 SFYApplication クラスにて上書き実装した、 SFYApplication::HandleEvent / SFYApplication::HandleRender 関数が呼び出されます。

[Note] 注意

SFEVT_APP_START / SFEVT_APP_RESUME / SFEVT_APP_STOP / SFEVT_APP_SUSPEND イベントを受信したとき、 必ず true を返す処理をしていることに注意してください。

SFYApplication::HandleEvent 関数は、 BREW イベントルート以下のレスポンダツリーに配信し、 必要に応じてルート以下のレスポンダツリーを再描画します (参照: イベント処理 / 描画処理)。

SFYApplication::HandleRender 関数は、 アプリ開始/再開時と優先的イベントハンドラ終了時に全画面(デバイス画面とルート以下のレスポンダツリー)を再描画します (参照: アプリ開始/再開時と優先的イベントハンドラ終了時の全画面再描画)。

SFYApplication::HandleEvent / SFYApplication::HandleRender / SFCApplication::HandleError 仮想関数のデフォルトの実装は、各関数の内部実装コードを参照してください。

これらの仮想関数は、アプリの処理内容に応じてユーザー定義アプリケーションクラスにて上書きしますが、 通常はデフォルトの実装で十分です。

参照: SFC アプリの全体的な処理の流れ

3.2.3. アプリの終了

アプリを終了するには、 SFCApplication::Terminate 関数を呼び出します。

SFCApplication::Terminate 関数を呼び出すと、 内部的に BREW API ISHELL_CloseApplet 関数が呼び出されます。 そのとき、アプリは SFEVT_APP_STOP イベントを受信し、 アプリケーションクラスのデストラクタを実行した後アプリケーションクラスのインスタンスは解放され、 アプリは終了します。

SFYApplication::~SFYApplication デストラクタは、 テキスト入力コントロールエディタ、 レスポンダツリー描画エンジン配信エンジンを終了し、 リソースをすべて解放します。

SFCApplication::~SFCApplication デストラクタは、 アプリが BREW イベントを処理しない設定にします。

利用者が電源キー(AVK_POWER)を押下した場合、 もしくはクリアキー(AVK_CLR)を押下時にアプリが AEE に false を返した場合、 SFCApplication::Terminate 関数呼び出しと同等の処理が自動的に行われてアプリは終了します。

[Note] 注意

クリアキー(AVK_CLR)の SFEVT_KEY イベントはアプリ側で処理できますが、 電源キー(AVK_POWER)の SFEVT_KEY イベントはアプリ側では処理できません。

[Note] 注意

SFCApplication::Terminate 関数は、 レスポンダを破棄するための SFYResponder::Terminate 関数とは処理内容が異なります。

参照: アプリケーションクラス(基礎編)