onDraw内でinvalidateを呼び出してしまうカスタムビューを作ってしまって、困ったこと
問題となったのは、こいつ!
android.view.View#invalidate
Viewの再描画をマークするメソッドです。
OverrideしたonDraw内でうっかりこいつを呼び出してしまったところ、ActivityにAllocateされたメモリが解放されなくなってしまう問題が発生。
再現の流れ
Activity Aでたくさんの画像を読み込む(BitmapFactory.decodeResourceとかそういうやつ)
V
Activity Bに遷移
(上述の困ったViewを使うレイアウトを指定しておく)
V
”すぐに”Activity Aに遷移
あら不思議、Allocateが前の続きから増えていく。
何回も繰り返すと、OutOfMemoryErrorが起きて再起動されます。
android.view.View#invalidate
Viewの再描画をマークするメソッドです。
OverrideしたonDraw内でうっかりこいつを呼び出してしまったところ、ActivityにAllocateされたメモリが解放されなくなってしまう問題が発生。
再現の流れ
Activity Aでたくさんの画像を読み込む(BitmapFactory.decodeResourceとかそういうやつ)
V
Activity Bに遷移
(上述の困ったViewを使うレイアウトを指定しておく)
V
”すぐに”Activity Aに遷移
あら不思議、Allocateが前の続きから増えていく。
何回も繰り返すと、OutOfMemoryErrorが起きて再起動されます。
ProgressDialog
ProgressDialogに
setInverseBackgroundForced(true)を設定すると、
ProgressDialog.STYLE_SPINNER
ProgressDialog.STYPE_HOLIZONTAL
が表示されなくなる。
falseなら平気。
続きは、ソース例。
setInverseBackgroundForced(true)を設定すると、
ProgressDialog.STYLE_SPINNER
ProgressDialog.STYPE_HOLIZONTAL
が表示されなくなる。
falseなら平気。
続きは、ソース例。
リソースのLocalization
Androidアプリのリソース
res/value/strings.xml
res/value-en/strings.xml
res/value-ja/strnigs.xml
などを一元管理できるビュー作ろうかな。
レイアウト・・・は厳しそうだな。
res/value/strings.xml
res/value-en/strings.xml
res/value-ja/strnigs.xml
などを一元管理できるビュー作ろうかな。
レイアウト・・・は厳しそうだな。
<jp.moriko.sample.animation.AnimView android:id="@+id/image"
android:layout_width="80dp" android:layout_height="80dp"
default="@drawable/test_bitmap"
/>
こんな風に、カスタムビューに独自の属性を理解させるとき、
@drawable/test_bitmapという文字列から、
R.drawable.test_bitmapという値(int)を取得するにはどうしたらいいんだろう?
ImageViewのコンストラクタあたりから追っていったんだけど、
わかりませんでした。
TypeArrayが怪しい。
AssetManager.applyStyleの中がわかればわかるかも。
(でもnativeコードで書かれていて、ソースが見つからなかったんです)
音を鳴らそう
Androidアプリで音を鳴らすときの注意。
音源を扱うクラスを作って、
インスタンスがたくさんできる意味はないと思ったからシングルトンにして、
メモリリークを避けるためにApplicationContextを取ってきて渡してインスタンスを生成した。
すると、Activityを切り替わると音が出なくなる現象が発生。
たとえば、Activity 1のボタンを押したときに音を出して、Activity 2に切り替えるとする。
そうすると、Activity 2ではボタンの音が出ない。
Activity 1で押し続ける分にはいくらでも音が出るのにだ。
このとき、MediaPlayer.seekTo(int mSec)でIllegalStateExceptionが発生している。
リファレンスによると、seekToはPrepared、Started、Paused、Playback Completedのいずれかでないと使えない。
Activityが切り替わると、SoundManagerで用意したMediaPlayerが初期化されない状態に戻ってしまい、
seekToは使えません。startもstopも使えません。
と怒られてしまう。
おそらく、音はActivityに関連付けられていて、Activityが変わればまた作らなきゃいけないんだと思う。
続きには、うまく動かないソースコードと、うまく動くソースコード。
音源を扱うクラスを作って、
インスタンスがたくさんできる意味はないと思ったからシングルトンにして、
メモリリークを避けるためにApplicationContextを取ってきて渡してインスタンスを生成した。
すると、Activityを切り替わると音が出なくなる現象が発生。
たとえば、Activity 1のボタンを押したときに音を出して、Activity 2に切り替えるとする。
そうすると、Activity 2ではボタンの音が出ない。
Activity 1で押し続ける分にはいくらでも音が出るのにだ。
このとき、MediaPlayer.seekTo(int mSec)でIllegalStateExceptionが発生している。
>Attempt to perform seekTo in wrong state: mPlayer=インスタンスID, mCurrentState=ステート番号
リファレンスによると、seekToはPrepared、Started、Paused、Playback Completedのいずれかでないと使えない。
Activityが切り替わると、SoundManagerで用意したMediaPlayerが初期化されない状態に戻ってしまい、
seekToは使えません。startもstopも使えません。
と怒られてしまう。
おそらく、音はActivityに関連付けられていて、Activityが変わればまた作らなきゃいけないんだと思う。
続きには、うまく動かないソースコードと、うまく動くソースコード。




