SurfaceViewを使ってはいけない

はじめに

この記事は「みんコミ Advent Calendar」の20日目の記事です。

みんコミ」のAndroidアプリ(バージョン1.0.3)をベースに執筆しています。スクリーンショットは極力控える方針ですので、本記事を読む際には、「Google Play Store」からアプリをインストールしておくことをお勧めします。

en_generic_rgb_wo_60


abstract

別スレッドから描画でき、高速な描画が期待できるSurfaceViewは、描画にハードウェア支援(Hardware Acceleration)が適用されない。

Canvas in SurfaceView – hardware acceleration

Bitmapを描画するパフォーマンステストを実行したところ、通常のViewを拡張した描画と比較して、SurfaceViewによる描画は10倍以上遅いということがわかった(単位はnano second)。

View SurfaceView
142,590.55 1,989,301.12

以上のことから、描画速度を求めるのであればSurfaceViewではなく、Viewを継承したCustom Viewを実装することが適切である。

SurfaceView

「みんコミ」アプリのコミックビューアーには現在SurfaceViewが使われていると理解しています。

なぜそう思ったかというと、

  1. 最初のページで端末を横向きにして画面を回転させる。
  2. ページを拡大
  3. ページを縮小

すると、次のように描画にノイズが入るんですね。再描画時にCanvasがリセットされないのはSurfaceViewの特徴なので、きっとSurfaceViewを使っているのだろうと判断しました。

東皓司著 「ひとはくん、ひとりぼっち?」 2話 1ページ

東皓司著 「ひとはくん、ひとりぼっち?」 2話 1ページ

指摘した現象自体は簡単に解決できます。描画の最初にCavnasにdrawColorしてキャンバスを一度塗りつぶしてやれば良いだけです。

しかし今回は、表題の通り「SurfaceViewを使ってはいけない」という話です。

SurfaceView、使いますよね。
だって、コミックの大きな画像を滑らかに拡大縮小・スクロールしたいわけですから、普通は実装するときに「SurfaceView」を選択すると思います(もし違っていたらごめんなさい)。

SurfaceViewをつかってはいけない

SurfaceViewが速かったのは過去の話です。

突然こんなこと言ってごめんね。
でも本当です。

Android 4.0以降で標準で有効になっている「ハードウェアアクセラレーション」による描画支援を「View」は受けられますが、「SurfaceView」は受けられません。

Canvas in SurfaceView – hardware acceleration

すると、SurfaceViewで描画すると逆にViewより遅くなってしまうのです。

Why “SurfaceView” is slower than a custom “view”?

[00:38 追記]ベンチマークの条件を追記しました。

試しに、ViewとSurfaceViewでどの程度速度が違うのか、Nexus 5X(Android 6.0.1 – 給電状態)で、500×600のビットマップを1000回、描画して平均を取ってみました(単位はnano second)。

View SurfaceView
142,590.55 1,989,301.12

その差「10倍」以上です。

そう。僕たちが速度を求めて選んでいたSurfaceViewは、実はViewよりも遙かに遅いのです。
またSurfaceViewはCamera2 APIからはプレビューにも使えません。
それが今のSurfaceViewなんです。

なんでまだdeprecatedじゃないんでしょうか。これ。

一応、SurfaceViewの使いどころみたいなのを挙げるのであれば……例えば、サーバーから非同期にダウンロードするデータを描画していきたい場合でしょうか。
UIスレッド内のonDraw内でネットワーク通信はできませんし、複雑な処理をするとやはりANR(Application Not Responding)が発生してしまうことが予想されます。

[00:17 追記]そういう時にはTextureViewですね。

TextureViewのベンチマークも掲載しておきます。単純なBitmapの描画であればやはりViewの方が速いです。

View SurfaceView TextureView
142,590.55 1,989,301.12 518,378.38

Googleはもっと積極的に「SurfaceViewは使うな。Viewの方が速い」とアピールすべきだと思います。そうでないと、SurfaceViewを使って速度が上がらず呻く開発者がこれからも出続けるでしょう。

自戒を込めて。

あらためて、パフォーマンステスト(DrawPerformanceActivity)を含めたコードをGitHubに置いておきます。参考になれば幸いです。

https://github.com/keiji/adventcalendar_2015_mincomi


「有山圭二」は「みんなのコミック」及び運営の「株式会社イーブックイニシアティブジャパン」とは一切関係がありません。
また、本アドベントカレンダーの内容はあくまで参加者個人の見解です。
「みんなのコミック」の評価を目的とするものではありませんので、ご了承下さい。

みんコミといえば、僕が普段からお世話になっている根雪れい(@neyuki_rei)さんも連載していますね!

根雪さんの作品の更新は来年になるので、

人間以外にしか好かれない男の子が主人公です。ヒロインの「こまこ」の仕草が可愛いです。あと眉毛。

二話目になると単純に使い捨ての悪者かと思っていたキャラクターが再登場したり、最後には「これからストーリーが動き出すぞ」と、感じさせる引きがあったりと構成が上手いなぁと思います。

あ、眼鏡っ娘は出ません。
残念です。


それでは明日21日の担当は、ずっとSurfaceViewを信じてきたのに裏切られた気分の「有山圭二」さんです。

よろしくお願いします。


SurfaceViewを使ってはいけない」への1件のフィードバック

  1. ピンバック: みんなのコミック | めがねをかけるんだ

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です