レイアウトの圧縮
レイアウト圧縮では、ページのレンダリング パフォーマンスを向上するために、指定したレイアウトをビジュアル ツリーから削除します。 この記事では、レイアウト圧縮を有効にする方法と、それがもたらす利点について説明します。
概要
Xamarin.Forms では、一連の再帰メソッド呼び出しを 2 つ使用してレイアウトを行います。
- レイアウトは、ページのビジュアル ツリーの上部から始まり、ビジュアル ツリーのすべての分岐を通って、ページ上のすべてのビジュアル要素を網羅します。 他の要素の親である要素は、自分に対する相対的な子のサイズと配置を設定する必要があります。
- 無効化とは、ページ上の要素の変更が新しいレイアウト サイクルをトリガーするプロセスです。 要素は、正しいサイズや位置を持たなくなると、無効であるとみなされます。 子を持つビジュアル ツリー内のすべての要素は、その子のいずれかがサイズを変更するたびにアラートを受け取ります。 そのため、ビジュアル ツリー内の 1 つの要素のサイズ変更が、ツリーの上方へと波及する変化を引き起こす可能性があります。
Xamarin.Forms によるレイアウトの実行方法の詳細については、カスタム レイアウトの作成に関するページを参照してください。
レイアウト プロセスの結果として、ネイティブ コントロールの階層が得られます。 ただし、この階層には、プラットフォーム レンダラー用の追加のコンテナー レンダラーとラッパーが含まれているため、ビュー階層の入れ子がさらに増えます。 入れ子のレベルが深いほど、ページを表示するために Xamarin.Forms で実行する必要がある作業量が多くなります。 複雑なレイアウトの場合、ビュー階層は、複数のレベルの入れ子を含んだ、深く、広いものとなる可能性があります。
たとえば、Facebook にログインするためのサンプル アプリケーションの次のボタンについて考えてみます。
このボタンは、次の XAML ビュー階層を持つカスタム コントロールとして指定されます。
<ContentView ...>
<StackLayout>
<StackLayout ...>
<AbsoluteLayout ...>
<Button ... />
<Image ... />
<Image ... />
<BoxView ... />
<Label ... />
<Button ... />
</AbsoluteLayout>
</StackLayout>
<Label ... />
</StackLayout>
</ContentView>
結果の入れ子ビュー階層は、ライブ ビジュアル ツリーを使用して調べることができます。 Android では、入れ子ビュー階層には 17 のビューが含まれています。
レイアウト圧縮は、iOS および Android プラットフォーム上の Xamarin.Forms アプリケーションで使用でき、指定されたレイアウトをビジュアル ツリーから削除してビューの入れ子をフラット化することを目的としています。これでページレンダリングのパフォーマンスを向上できます。 こうして得られるパフォーマンス上の利点は、ページの複雑さ、使用しているオペレーティング システムのバージョン、このアプリケーションが実行されているデバイスによって異なります。 ただし、パフォーマンスが最も大きく向上するのは、古いデバイスの場合です。
Note
この記事では、Android にレイアウト圧縮を適用した結果に焦点を当てていますが、iOS にも同様に適用できます。
レイアウトの圧縮
XAML では、レイアウト クラスで CompressedLayout.IsHeadless
添付プロパティを true
に設定して、レイアウト圧縮を有効にすることができます。
<StackLayout CompressedLayout.IsHeadless="true">
...
</StackLayout>
または、CompressedLayout.SetIsHeadless
メソッドの最初の引数としてレイアウト インスタンスを指定して、C# で有効にすることもできます。
CompressedLayout.SetIsHeadless(stackLayout, true);
重要
レイアウト圧縮を行うとビジュアル ツリーからレイアウトが削除されるため、視覚的な外観を持つ、またはタッチ入力を受け付けるレイアウトには適していません。 したがって、VisualElement
プロパティ (BackgroundColor
、IsVisible
、Rotation
、Scale
、TranslationX
、TranslationY
など) を設定する、またはジェスチャを受け入れるレイアウトは、レイアウト圧縮の候補ではありません。 ただし、視覚的外観のプロパティを設定する、またはジェスチャを受け入れるレイアウトでレイアウト圧縮を有効にしても、ビルドまたはランタイムのエラーは発生しません。 代わりに、レイアウト圧縮が適用され、視覚的外観のプロパティとジェスチャ認識が通知なしで失敗します。
Facebook ボタンの場合、次の 3 つのレイアウト クラスでレイアウト圧縮を有効にすることができます。
<StackLayout CompressedLayout.IsHeadless="true">
<StackLayout CompressedLayout.IsHeadless="true" ...>
<AbsoluteLayout CompressedLayout.IsHeadless="true" ...>
...
</AbsoluteLayout>
</StackLayout>
...
</StackLayout>
Android では、これで 14 のビューを含む入れ子ビュー階層が作成されます。
17 のビューを持つ、元の入れ子ビュー階層と比較すると、これはビューの数が 17% 減少したことを表します。 この減少は重要でないように見えますが、ページ全体ではビューの減少はより重要になると考えられます。
高速レンダラー
高速レンダラーを使用すると、結果として得られるネイティブのビュー階層をフラット化して、Android 上の Xamarin.Forms コントロールの増加が抑制され、レンダリング コストが削減されます。 この場合、作成されるオブジェクトが少ないので、結果として、ビジュアル ツリーの複雑さが軽減され、メモリの使用量も少なくなり、パフォーマンスをさらに向上できます。 高速レンダラーの詳細については、「 高速レンダラー」を参照してください。
サンプル アプリケーションの Facebook ボタンの場合、レイアウト圧縮と高速レンダラーを組み合わせると、生成される入れ子ビュー階層のビュー数は 8 つになります。
17 のビューを持つ、元の入れ子ビュー階層と比較すると、これは 52% 減少したことを表します。
このサンプル アプリケーションには、実際のアプリケーションから抽出されたページが含まれています。 レイアウト圧縮と高速レンダラーを使用しない場合、Android 上ではこのページに 130 のビューを持つ入れ子ビュー階層が生成されます。 適切なレイアウト クラスで高速レンダラーとレイアウト圧縮を有効にすると、入れ子ビュー階層のビューが 70 に減り、46% 減少します。
まとめ
レイアウト圧縮では、ページのレンダリング パフォーマンスを向上するために、指定したレイアウトをビジュアル ツリーから削除します。 この操作によって得られるパフォーマンスのメリットは、ページの複雑さ、使用しているオペレーティング システムのバージョン、このアプリケーションが実行されているデバイスによって異なります。 ただし、パフォーマンスが最も大きく向上するのは、古いデバイスの場合です。