後始末系の処理の覚え書き
関連事項>
HTCでテストしてたときに発生した時に
ImageViewでandroid:src で設定済の物に対して
setImageResourceをしたらOutOfMemoryが・・・
まあー度あることは二度ある感じなんで
色々とよく使う後始末系の処理を覚え書きとしてまとめてみようかと。
まあここら辺の処理は遣っている人は当たり前として遣っていると思うので
あくまで自メモですね。。
上記の処理に関しては
setImageResourceをdecodeResourcesetImageBitmapにしたらかなりOutOfMemoryError防げるぽい
2010-08-12 11:52:40 via web
な呟きもみたので試してみたんだけど、それだけでは駄目。
最終的には下記の対応で落ち着きました
まあこれとは別にアプリ終了時にメモリクリアとかしてあげないと
結構残るっぽい。onDestoryで呼ぶのがよい感じ
一応正式な記述的には
- isRecycle() => recycle() らしいんですけど、判定しなくても落ちることはないので問題ないと思う
あとはAndroidはなんかプロセスが残り気味なので
下記のような強制終了の処理を入れていたりしてます
あとはAd入れているとキャッシュが溜まるので
チョコチョコ消している感じ(Unityで振り返りざまにSystem.gcとかしてると同じ感じかな)
これはAndroid3.0だけで起こる奴なんですけど,Animation効果が残る問題。*1
//ivはImageViewとか
iv.clearAnimation();
iv.invalidate();
をしておきましょうと言うお話
追記>
つい最近だとAndroid4.1移行だとAnimation系は結構動かなくなってる
で置き換えメモはまとめた。
とくにRelativeLayoutの重ねがけ等はヤバゲ ><
追記)
OutOfMemoryのAndroidRuntimeはどうしても回避できないので
GIMPで
画像=>モード=>インデックス(RGBから
ファイル=>エクスポート
あたりにすると、画像サイズが劇的に減ります(1/2〜1/4程度に)
なお話もあるようですが、こちらの方が手軽ですね
追記2)
の状況が発生*2
HTC Desire だと本当にメモリ厳しくなって来た時は copyのメモリ確保もダメか。BitmapFactory.decodeResource & bmfOptions.inPurgeable = true; bmfOptions.inScaled = false; でOK
直接setImageBitmap で何とかなってるけど、うーんこの機種だけなのかすごく謎
追記3)
キャッシュクリア系生きてくるのは下記の条件下みたい*3
android File file = new File(getCacheDir(), "ファイル名") ;でキャッシュに書くのはいいけど、DataCleanerみたいな キャッシュ、アプリデータの定期削除ってどう実装すればいいんだろう?
- Preference保存の場合は以下
SharedPreferences.Editor editor = getSharedPreferences("favorite", 0); editor.clear().commit();
- private領域なら下記な感じかも
for(String fname:fileList()){
deleteFile(fname);
}
- SD領域なら*4
private File getSDCardDir(){ File dir = null; if(Build.VERSION.SDK_INT >= 8){ dir = ActivityUtil.getExternalFilesDir(this,null); } else{ dir = new File(Environment.getExternalStorageDirectory(),"/Android/data/" + getClass().getPackage().getName() +"/files"); dir.mkdirs(); } return dir; }
@SuppressLint("NewApi") public class ActivityUtil { public static File getExternalFilesDir(Activity activity,String type){ return activity.getExternalFilesDir(type); }
WebCashedはここ)
追記4)
つい最近ロギングラッパーの話でHeapdumpの話を追加してみた。
でもこれ根本解決にならんからあんま好きではないんだよな。。。*5
どうしてもダメなときは下記みたいな対応も有る。
(layout.xml に android:backgroundで画像を指定しまくっている時)
BitmapFactory.Options bmfOptions = new BitmapFactory.Options(); bmfOptions.inPurgeable = true; if("htc_wwe".equals(Build.BRAND) && "HTC Desire".equals(Build.MODEL)){ bmfOptions.inSampleSize=2; } Bitmap bt = BitmapFactory.decodeResource(m_r, res_id,bmfOptions);
なのが推奨されているけど、読み込む画像が崩れるのでオススメはしないし、
ここでもコメントしたけど
layout.xmlに定義されているものには無力。この場合は
BitmapFactory.decodeResource(m_r, resid)
- な感じで原寸で読み込まれる
- =>レイアウトで伸縮 される動きになるよう*6
所謂
layout/result.xml
<Linerlayout xmlns:android="http://schemas.android.com/apk/res/android" android:background="@drawable/back_result" android:gravity="center_horizontal" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent"> </Linerlayout>
な指定の仕方のケース。*7
でその場合はどうするかというと
m_r = getResources(); if("htc_wwe".equals(Build.BRAND) && "HTC Desire".equals(Build.MODEL)){ WindowManager windowManager = getWindowManager(); Display display = windowManager.getDefaultDisplay(); final DisplayMetrics displayMetrics = new DisplayMetrics(); display.getMetrics(displayMetrics); Configuration config = m_r.getConfiguration(); displayMetrics.densityDpi = DisplayMetrics.DENSITY_MEDIUM;//.DENSITY_LOW; m_r.updateConfiguration(config, displayMetrics); }
で強引にディスプレイ解像度の画像深度を変更すると。これでも凄い暫定対応ですけどね・・。*8
結局は対象解像度用の画像をすべて用意してもらうのがいいんですけど
なので自分で画像を加工する技術をつけるかしかないのかなと思う。
自分だと画像をgimpでインデックスカラーにするくらいが精一杯。
実際はリサイズして画像データサイズを減らすべきなんだよな。。
参考リンク集)