APLテンプレートのデザインを最適化する


APLテンプレートのデザインを最適化する

APLには、APLドキュメントとレイアウトをより効率的に構成するために役立つさまざまなUIコンポーネントが用意されています。また、一定のコンセプトに従うことで、実行時にリソース効率の高い方法でコンポーネントを使用できます。テンプレートのデザインの効率性は、次の2つの点から評価できます。

  • APLテンプレートコードの効率性。保守性の向上を目的とした最適化に適しています。
  • インフレートされたAPLドキュメントの実行時の効率性。パフォーマンスの向上を目的とした最適化に適しています。

両方の効率化目標は連動するように見えるかもしれませんが、常にそうとは限りません。APLテンプレートデザインを選択するときは、その結果としてインフレートされたAPLドキュメントがどのように表示されるかを理解する必要があります。

モジュール式のテンプレートデザインで再利用性を高める

APLドキュメントの読みやすさと保守性を高めるAPLテンプレートコードを作成して構成すると、効率が向上するとともに、多くの場合、冗長なAPLコードが排除され、モジュール式のテンプレート構造が構築されます。たとえば、APLのレイアウト定義やスタイル定義を使用することはモジュール式のアプローチです。このアプローチを採用すると、通常、テンプレートのファイルサイズが小さくなります。また、APLドキュメントのインフレート時にデバイス上のAPLランタイムでダウンロードして解析する必要のあるバイト数が減るため、パフォーマンスにもメリットが生じる可能性があります。

一般的に目指すべき目標は、テンプレート内のAPLコンポーネントの再利用性を高めて、モジュール性を確立し、可能な限り冗長性を減らすことです。APLには、モジュール式のテンプレートデザインを実現するためのさまざまなオプションが用意されています。

  • APLレイアウトを使用する - APLのレイアウトは、繰り返し使用される視覚的なUIコンポーネントを分離する方法として役立ちます。レイアウトのコンテンツと動作を動的にカスタマイズする入力パラメーターを追加して、レイアウトを再利用可能にすることができます。レイアウトは入れ子にもできるため、レイアウトに反復構造が含まれている場合は、分割して入れ子にすることでさらなる最適化が可能です。詳細については、APLレイアウトを参照してください。
  • APLスタイルを使用する - APLのスタイル定義を使用すると、スタイル設定可能プロパティのセットを複数のAPLコンポーネント間で再利用できます。1つ以上のテンプレートで複数のAPLコンポーネントが同じスタイルプロパティを共有しているパターンを見つけたら、それらのプロパティを切り出して、一元的なAPLスタイル定義にまとめることをお勧めします。APLスタイルの詳細を確認してください。
  • APLリソースを使用する - 文字列、数値、色コード、ディメンション値、イージング関数などの静的リソースがテンプレート内で繰り返し使用されている場合は、テンプレートでそれらをリソースとしてグローバルに定義することを検討してください。APLのリソースの詳細を確認してください。
  • APLスタイルの継承を使用する - APLスタイルは、継承によってさらに効率的に使用できます。同じようなスタイル設定可能プロパティのセットを使用するカスタムスタイル定義が2つ以上ある場合は、共通するプロパティ値のセットを切り出して、独自の基本スタイル定義を作成することを検討してください。APLスタイルの継承の詳細を確認してください。
  • ユーザー定義APLコマンドを使用する - 複数のAPLコンポーネントやそれらのイベントハンドラープロパティ間に共通するUI動作がある場合、APLコマンドのグループ自体も繰り返される傾向があります。テンプレート内に同じようなAPLコマンドブロックのセットがある場合は、それらを1つのユーザー定義APLコマンドにまとめることを検討してください。また、ボタンの押下などのUIイベントと同じアクションをユーザーが音声でリクエストしたら、そのイベントの効果を再現するために、AlexaスキルコードでAPLテンプレートのコマンドシーケンス全体を複製することが必要になる場合があります。UIイベントハンドラーのコマンドをユーザー定義コマンドとして再利用可能にすれば、ボタンの押下などの対応するUIイベントにAPLドキュメントが応答する場合と同じように、スキルからそのコマンドの実行をリクエストできるようになります。ユーザー定義コマンドの詳細を確認してください。
  • カスタムAPLパッケージを使用する - カスタムパッケージとは、ほかのAPLドキュメントにインポートできる再利用可能なAPLドキュメントです。APLドキュメントをパッケージとしてインポートする機能は、レイアウト、リソース、ユーザー定義コマンド、スタイルなどの再利用可能なAPLアーティファクトを、いくつかのAPLドキュメントテンプレートで共有するために役立ちます。APLパッケージの詳細を確認してください。

再利用性を活用すれば、テンプレート全体のデザインの一貫性も確保されます。たとえば、スタイルプロパティ値やレイアウトコンポーネントに加えられた変更は、それぞれのスタイルまたはレイアウトを参照するすべての依存視覚コンポーネントに自動的に適用されます。関連するAPLコンポーネントやプロパティがテンプレート間で複製されている場合、このような更新の必要性は見落とされがちです。

類似するAPLコンポーネントを一元的なレイアウト、スタイル、リソースなどにマージするときは、それらのコンポーネントを暗黙的に均一化することになる点に注意してください。このため、個々のAPLコンポーネントを後でカスタマイズする場合の柔軟性は低下します。類似する複数のAPLコンポーネントでベースを共有するのが合理的か、それとも後で変更が必要になる可能性があるかをよく検討してください。

テンプレートデザインのコストを下げる

デザインの低コスト化とは、テンプレート内でのAPLコンポーネントの使用を最小限に抑えながら、APLデザインの目標を達成することを指します。APLコンポーネントの数を減らし、テンプレート自体のサイズを小さくするには、モジュラー式のデザインを確立して再利用性を高めるのが効果的な方法です。ただしこれは、実行時の効率的な使用を保証するものではありません。デザインの低コスト化は、パフォーマンスの最適化にもつながります。これは、画面付きデバイスのAPLランタイムによってAPLドキュメントが処理された後、不必要にインフレートされたり保持されたりするAPLコンポーネントの数が少なくなるためです。

インフレートされるAPLドキュメントからAPLコンポーネントを除外する場合は、コンポーネントのdisplayプロパティを使用して非表示にするのではなく、常にwhenプロパティを使用してコンポーネントの作成自体を回避します。ただし、whenプロパティはドキュメントのインフレート時に1回しか評価されないため、ドキュメントのレンダリング後にコンポーネントを表示する方法はないことに注意が必要です。

次のようなコードがあるとします。

{
    "type": "Container",
    "display": "${@viewportProfileGroup == @tv ? 'normal' : 'none'}",
    "items": [
        ...
    ]
}

これは、次のようにした方が効率的です。

{
    "when": "${@viewportProfileGroup == @tv}",
    "type": "Container",
    "items": [
        ...
    ]
}

同じように表示される複数のAPLコンポーネントをdisplayで切り替えることは望ましくありません。

次のようなコードがあるとします。

{
    "type": "Text",
    "display": "${isOn ? 'normal' : 'none'}",
    "text": "オン"
},
{
    "type": "Text",
    "display": "${isOn ? 'none' : 'normal'}",
    "text": "オフ"
}

これは、次のようにした方が効率的です。

{
    "type": "Text",
    "text": "${isOn ? 'オン' : 'オフ'}"
}

ContainerFrameなどの構造的なAPLコンポーネントとレイアウトを必要以上に使用することは避け、除外できる場合は除外します。コンポーネントツリーもフラットな方が読みやすくなります。

次のようなコードがあるとします。

{
    "type": "Container",
    "width": "50vw",
    "items": {
        "type": "Frame",
        "backgroundColor": "red",
        "item": { ... }
    }
}

これは、次のようにした方が効率的です。

{
    "type": "Frame",
    "width": "50vw",
    "backgroundColor": "red",
    "item": { ... }
}

ContainerGridSequenceSequenceなどの複数子コンポーネントでは、データ配列のインフレートを使用して、列挙やリストなどの反復的なコンポーネント構造を解消します。

次のようなコードがあるとします。

{
    "type": "Container",
    "items": [
      {
        "type": "Text",
        "text": "1)リンゴ"
      },
      {
        "type": "Text",
        "text": "2)バナナ"
      }
    ]
}

これは、次のようにした方が効率的です。

{
    "type": "Container",
    "data": [ "リンゴ", "バナナ" ],
    "items": [
      {
        "type": "Text",
        "text": "${index+1})${data}"
      }
    ]
}

Textコンポーネントを過度に使用せず、テキストを結合できる場合は結合します。Textコンポーネントのマークアップタグのサポートが役立ちます。

可能であれば、次のようなコードは避けます。

{
    "type": "Container",
    "items": [
      {
        "type": "Text",
        "color": "red",
        "text": "赤、"
      },
      {
        "type": "Text",
        "color": "yellow",
        "text": "黄色"
      }
    ]
}

これは、次のようにした方が効率的です。

{
    "type": "Text",
    "text": "<span color='red'>赤</span><br><span color='yellow'>黄色</span>"
}

textプロパティ自体の頻繁な更新が想定される場合は、可能であれば、動的なテキスト専用のTextコンポーネントを用意して、相対サイズまたは絶対サイズを指定します。Textコンポーネントのディメンションの計算は、APLランタイムにとってコストの高い操作です。


このページは役に立ちましたか?

最終更新日: 2025 年 11 月 26 日