« 第3回勉強会@岡山を開催しました | トップページ | 11月15日のトレーニング »

2010年11月15日 (月)

SQLiteをAndroidから利用する時の注意点

中国GTUGの勉強会ででてきて、時間がなかったので、
当日には解決できなかったので、いろいろと調べてみました。

すると、SQLiteOpenHelperがどうやって、SQLiteDatabaseを管理しているのかが
わかりました。

これがわかると、SQLiteOpenHelper#onCreateと
SQLiteOpenHelper#onUpgradeがどんな時に呼ばれるのかが
分かってきます。

結論を言うと、onCreate() or onUpgrade()が呼ばれるのは、アプリケーションが
起動されて、最初にSQLiteOpenHelper#getWritableDatabaseか、
SQLiteOpenHelper#getReadableDatabaseが呼ばれるタイミングで
メソッドが呼ばれることになります。

で、SQLiteDatabaseはSQLiteOpenHelperが管理するのですが、
最初にインスタンスを生成した後、メンバ変数に退避されます。
(戻り値も参照したものを返します)

SQLiteDatabase#getWriableDatabaseの実装が以下のようなものに なっていますので、2回目以降だとメンバ変数の参照を返すように なりますので、closeを呼ぶ時は注意が必要です。

        if (mDatabase != null && mDatabase.isOpen() && !mDatabase.isReadOnly()) {

            return mDatabase;  // The database is already open for business
        }

特にContentProviderのようにcloseのタイミングが取りにくい(というか、取れない気がする)
場合などは、closeした後、再度SQLiteOpenHelperからSQLiteDatabaseを
取ると、closeされた状態のインスタンスが返される可能性があります。

なので、この時点で考えられる方法としては、

1. closeと一緒にSQLiteOpenHelperにnullを代入する。(再利用時はインスタンス生成する)
2. closeをしない。

上記の2つになると思います。

1.しかないだろ?と思われますが、実は2.でいいのです。
その理由は、SQLiteDatabaseで#finalizeが実装されていて、
ここで、closeとほぼ同じ処理が書かれています。

finalizeはObjectクラスのメソッドですので、
VM(Androidの場合はDalvik-VM)のGC実行時に呼び出されて
無事、close処理が実行されます。

ということから、SQLiteDatabaseも色々考えられている事がわかります。

ただし、Cursor#closeはしっかり呼んだ方がいいです。
これはInterfaceなので、どんな実装になっているかわかりませんので、
明示的に呼ばなければいけません。
closeをしてないと、メモリ圧迫の原因になります。
(LogCatにはたまに(毎回?)警告メッセージが出力されます。)

|

« 第3回勉強会@岡山を開催しました | トップページ | 11月15日のトレーニング »

Android」カテゴリの記事

コメント

コメントを書く



(ウェブ上には掲載しません)




トラックバック

この記事のトラックバックURL:
http://app.cocolog-nifty.com/t/trackback/50625/50032694

この記事へのトラックバック一覧です: SQLiteをAndroidから利用する時の注意点:

« 第3回勉強会@岡山を開催しました | トップページ | 11月15日のトレーニング »