SurfaceViewによる高速描画 (1/5)
作成:2010-10-31 12:13
更新:2010-10-31 12:13
更新:2010-10-31 12:13
■SurfaceViewとは?
ゲームなどのアプリでは、コンポーネントを組み合わせるのではなく、グラフィックを使ってすべての表示を独自に描いていきます。こうしたときには、たいていViewを継承したクラスを定義し、その中で描画を行ないます。
が、Viewを使ったクラスは万能ではありません。特に問題となるのが「速度」です。Viewは、決して高速な描画に向いたものではありません。
ちょっと内部的な話になってしまいますが、Androidのプログラムというのは、ユーザーインターフェイスを扱うための「UIスレッド」と呼ばれるスレッドから処理が呼び出され実行されるようになっています。UIスレッドは、文字通りユーザーインターフェイス関連のすべてのイベント等が実行されるもので、この単一のスレッド内からすべてのコンポーネント類のイベント処理などが呼び出されているわけです。
Viewによる表示の更新(onDrawメソッド)なども、やはりこのUIスレッドからイベントの処理が呼び出されています。つまり、すべてのユーザーインターフェイス関係は、1つのスレッド内で順番待ちして自分が呼び出されるのを待っているのです。描画の更新だけが、順番をすっ飛ばして優先的に処理されるわけではありません。
どうしてこういう仕組みになっているのかというと、これは設計した人間に聞いてみないとわかりませんが、ひょっとしたら「Androidのコンポーネントがマルチスレッドに対応していない」ということと関係しているかも知れません。そう、コンポーネント類は、マルチスレッド非対応なのです。ですから、例えば別スレッドを用意してそこから無理やりViewの表示を更新しようとしても、(そのままでは)エラーになってしまいます。別スレッドで処理させるには、そのスレッドから、UIスレッドに更新処理の呼び出しを登録してやって、それが呼び出される順番待ちをする、というようなことになってしまいます。
この「全部が1つのスレッドで順番待ちしながら処理していく」というやり方は、速度を要求されな場合はシンプルでいいのですが、高速描画を必要とするリアルタイムゲームなどでは足かせとなってしまいます。
こうしたときに用いられるのが、「SurfaceView」と呼ばれるコンポーネントです。これはViewのサブクラスですが、Viewとはかなり使い方が違ってます。
SurfaceViewでは、UIスレッドとは無関係に描画の更新を行うことができます。またマルチスレッドで処理するための専用クラスをもっており、それを使ってUIスレッドとは別に独自にスレッドを使った処理を行わせることができます。
非常に便利ですが、その代りに使い方がちょっと面倒になっています。まず描画ですが、これはViewのように「onDrawメソッドをオーバーライドしておけば必要に応じて描画される」というような形にはなっていません(まぁ、一応onDrawも使うことはできるのですが、SurfaceViewを利用するようなケースではまずonDrawは使わないでしょう)。必要に応じて描画の更新を自分で行わなければいけません。
また、自動的にonDrawなどが呼ばれませんから、表示が更新されたときに何かをするような場合には、専用のコールバック機能を使い、処理を組み込むなどしなければいけません。またマルチスレッド処理も、通常のThreadクラスなどではなく、専用のクラスを使うことになります。
Viewで当たり前に使っていた基本的なコンポーネントの機能はすべて捨て、SurfaceView独自の機能を改めて覚えなおさないといけない――そう考えてください。
が、Viewを使ったクラスは万能ではありません。特に問題となるのが「速度」です。Viewは、決して高速な描画に向いたものではありません。
ちょっと内部的な話になってしまいますが、Androidのプログラムというのは、ユーザーインターフェイスを扱うための「UIスレッド」と呼ばれるスレッドから処理が呼び出され実行されるようになっています。UIスレッドは、文字通りユーザーインターフェイス関連のすべてのイベント等が実行されるもので、この単一のスレッド内からすべてのコンポーネント類のイベント処理などが呼び出されているわけです。
Viewによる表示の更新(onDrawメソッド)なども、やはりこのUIスレッドからイベントの処理が呼び出されています。つまり、すべてのユーザーインターフェイス関係は、1つのスレッド内で順番待ちして自分が呼び出されるのを待っているのです。描画の更新だけが、順番をすっ飛ばして優先的に処理されるわけではありません。
どうしてこういう仕組みになっているのかというと、これは設計した人間に聞いてみないとわかりませんが、ひょっとしたら「Androidのコンポーネントがマルチスレッドに対応していない」ということと関係しているかも知れません。そう、コンポーネント類は、マルチスレッド非対応なのです。ですから、例えば別スレッドを用意してそこから無理やりViewの表示を更新しようとしても、(そのままでは)エラーになってしまいます。別スレッドで処理させるには、そのスレッドから、UIスレッドに更新処理の呼び出しを登録してやって、それが呼び出される順番待ちをする、というようなことになってしまいます。
この「全部が1つのスレッドで順番待ちしながら処理していく」というやり方は、速度を要求されな場合はシンプルでいいのですが、高速描画を必要とするリアルタイムゲームなどでは足かせとなってしまいます。
こうしたときに用いられるのが、「SurfaceView」と呼ばれるコンポーネントです。これはViewのサブクラスですが、Viewとはかなり使い方が違ってます。
SurfaceViewでは、UIスレッドとは無関係に描画の更新を行うことができます。またマルチスレッドで処理するための専用クラスをもっており、それを使ってUIスレッドとは別に独自にスレッドを使った処理を行わせることができます。
非常に便利ですが、その代りに使い方がちょっと面倒になっています。まず描画ですが、これはViewのように「onDrawメソッドをオーバーライドしておけば必要に応じて描画される」というような形にはなっていません(まぁ、一応onDrawも使うことはできるのですが、SurfaceViewを利用するようなケースではまずonDrawは使わないでしょう)。必要に応じて描画の更新を自分で行わなければいけません。
また、自動的にonDrawなどが呼ばれませんから、表示が更新されたときに何かをするような場合には、専用のコールバック機能を使い、処理を組み込むなどしなければいけません。またマルチスレッド処理も、通常のThreadクラスなどではなく、専用のクラスを使うことになります。
Viewで当たり前に使っていた基本的なコンポーネントの機能はすべて捨て、SurfaceView独自の機能を改めて覚えなおさないといけない――そう考えてください。
(by. SYODA-Tuyano.)
※プログラムリストが表示されない場合
AddBlockなどの広告ブロックツールがONになっていると、プログラムリスト等が表示されない場合があります。これらのツールをOFFにしてみてください。
※関連コンテンツ