Re: [Android-SDK-Japan:2747] ViewGroup の invalidate()メソッドについて

3,232 views
Skip to first unread message

Keiji Ariyama

unread,
Jan 29, 2013, 12:11:27 AM1/29/13
to android-...@googlegroups.com
有山と申します。

 検証用のコードを拝見して、現象を確認しました。

 バージョンによってinvalidate()での描画の挙動が異なる現象には、ハード
ウェアアクセラレーションの有効無効が影響しているものと思われます。

 試しに、AndroidManifest.xmlに、hardwareAccelerated="false"を追加する
と、invalidate()のタイミングで全ての子ビューが再描画されるようになりました。

<application
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme"
android:hardwareAccelerated="false"
>

 ハードウェアアクセラレーションは、API Level 11(Honeycomb)から導入され
ました。API Level 14(ICS)以降は、標準で有効の状態に設定されています。

 AndroidManifestでtargetSdkVersionを、導入以前のバージョンにすると、標
準で無効になるので、全てが同じ挙動で動作するようになるということです。

 詳細な記述は下記のリンクを参考にして下さい。
『ハードウェアアクセラレーションによる描画モデルは、本当に再描画が必要
(DIRTY)な部分のみを描画する』との記述があります。

Hardware Acceleration - Hardware accelerated drawing model
http://developer.android.com/guide/topics/graphics/hardware-accel.html#hardware-model


(1/28/13 9:43 AM), Masamichi Yoshii wrote:
> 初めまして。吉井と申します。
>
> LinearLayout の
> invalidate()メソッドを呼び出した場合、配下の全ての子Viewを再描画してくれると思っていたのですが、これがどうもこれがうまく動かないケースがありました。いろいろ試してみたところ、どうも機種によって動きが違うようです。
>
> Xperia SO-01B (Android2.3.3) --- 再描画する
> AquosPhone SH-01D (Android4.0.4) --- 再描画しない
> Nexus7 (Android4.2.1) --- 再描画しない
>
>
> この結果を見るり、4.xで動きが変わったようにも見えます。そこでエミュレータで確認してみたところ、不思議なことにこちらはどんなバージョンでもちゃんと子Viewを再描画してくれました。(2.1,
> 2.3.3, 3.2, 4.1.2, 4.2 で確認)
>
> 更にもう一つ分かったのは、上の結果は全て targetSdkVersion="16" で確認していましたが、これを
> targetSdkVersion="10" (Android2.3.3)にすると、どの機種でも再描画してくれるようになりました。
>
> 確認方法は、親の invalidate() を呼び出し、子Viewの onDraw() が呼び出されるかどうかをチェックしました。確認コードを
> Github に置いておきました。
>
> https://github.com/masamichi441/AndroidInvalidateTest/blob/master/src/com/example/android/test/MainActivity.java
>
> invalidate()はもともとViewのメソッドであり、ViewGroupでもオーバーライドしていないようなので、子Viewに関しては関知しないよというのであれば、まあそれはそれで納得もできるのですが、実際にバージョンや機種によって(またはエミュレータ環境では)子Viewの再描画もしているので、どうにもすっきりしません。
>
> どなたかこの辺り、ご存じの方は教えてください。
>

--
Keiji,
ml_an...@c-lis.co.jp

Masamichi Yoshii

unread,
Jan 29, 2013, 7:33:47 AM1/29/13
to android-...@googlegroups.com
有山さん

ありがとうございます。謎が解けました。不可解な動作もこれで全て説明が付きます。それにし
てもこんな所に落とし穴があるとは。

解説ページの内容を完全に理解できたわけではないのですが、取りようによってはハードウェア
アクセラレーション描画モデルでも、第一フェーズでビュー階層を invalidate してくれるよう
にもとれます…が、すぐ後に確実に描画するためには(たぶんViewの)invalidate()を呼ぶ必要が
あるともあるので、やはりそれぞれのViewに対して個別にinvalidate()して置いた方が安全な
ようです。

とにかくこれだけのために hardwareAccelerated="false" にするのも本末転倒なので、この部
分は心しておきたいと思います。本当にありがとうございました。

吉井


2013年1月29日火曜日 14時11分27秒 UTC+9 C-LIS Keiji Ariyama:
Reply all
Reply to author
Forward
0 new messages