Android StrictモードでANRなどをなるべくなくす
StrictModeとは、メインスレッド内で予期せぬディスクアクセスや、ネットワークアクセスなどにより時間がかかる処理などをしている場合、それを教えてくれます。より、サクサク動くアプリを作るための、開発者向けのクラスです。
つまり、これを使って時間がかかっている処理を暴けば、ANRが少なくできるであろう!というわけです。
http://developer.android.com/reference/android/os/StrictMode.html
これを実装してみます。
単一の画面で調べたい場合は、その画面のActivityのOnCreateに書けばよいのですが、あらゆる画面で調べたい!と欲張りな私は、以前にGoogle Playで配布しないアプリにクラッシュログ機能を実装するで書きました、MyApplication.javaの中で実装します。
public class MyApplication extends Application { @Override public void onCreate() { // The following line triggers the initialization of ACRA super.onCreate(); ACRA.init(this); Log.d("Application", "MyApplication"); if (AppConstants.IS_STRICT_ON) { StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder() .detectDiskReads() .detectDiskWrites() .detectNetwork() // or .detectAll() for all detectable problems .penaltyLog() .build()); StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder() .detectLeakedSqlLiteObjects() .detectLeakedClosableObjects() .penaltyLog() .penaltyDeath() .build()); } } }
アプリを実行します。
すると、とある処理で、アプリが落ち、LogCatにエラーが表示されます。
06-25 13:10:43.585: E/StrictMode(21309): Finalizing a Cursor that has not been deactivated or closed. database = /data/data/hogehoge.appli/databases/hoge, table = null, query = select * from LocationTable 06-25 13:10:43.585: E/StrictMode(21309): android.database.sqlite.DatabaseObjectNotClosedException: Application did not close the cursor or database object that was opened here 06-25 13:10:43.585: E/StrictMode(21309): at android.database.sqlite.SQLiteCursor.<init>(SQLiteCursor.java:98) 06-25 13:10:43.585: E/StrictMode(21309): at android.database.sqlite.SQLiteDirectCursorDriver.query(SQLiteDirectCursorDriver.java:50) 06-25 13:10:43.585: E/StrictMode(21309): at android.database.sqlite.SQLiteDatabase.rawQueryWithFactory(SQLiteDatabase.java:1322) 06-25 13:10:43.585: E/StrictMode(21309): at android.database.sqlite.SQLiteDatabase.rawQuery(SQLiteDatabase.java:1261) 06-25 13:10:43.585: E/StrictMode(21309): at hogehoge.appli.helper.SqliteDataBaseHelper.getAllData(SqliteDataBaseHelper.java:163)
なぬっ
SQLiteのSELECTで使うカーソルが、閉じ忘れだそうです。
Cursor c = db.rawQuery("select * from " + SqliteDataBaseHelper.DB_TABLE, null); //この後 c.close(); を実装しなければならなかったのに忘れていた
ふぅ~
見つかってよかった
と、このように便利なツールですね!!
ちなみに、
http://developer.android.com/reference/android/os/StrictMode.html
を読んで勉強になったのが、Androidのファイルシステムは通常フラッシュメモリなので、I/Oが早いはずなのですが、他のプロセスと並行するためのメモリ割り当ては大変少ないので、他のプロセスと同時に書き込まれる場合はとっても遅くなる場合があるらしいです。