2012年2月14日火曜日

devfestx sapporo 2012 に参加した

非常に濃い2日間で、楽しかったです。特に Google の山崎さんは、フットワークが軽く、にこやかで、なるほど...グーグルが悪に感じるのは、きっと我々が悪だからなんだwww と、妙に納得した次第です。基本的にスピーカーの方々は、根明で謙虚で自分なりの価値観を持っている印象で、素晴らしかったと思います。1日目のハンズオンでは、Google Apps Script が大変勉強になりました。学習曲線で負荷のかかる場所と言えば、とっかかりの部分か、本格的にツッコミはじめる部分だと思うのですが、みんなで「わいわい」と手を動かしてコードを組むというのは、とても良かったです。MSオフィスのマクロみたいな事ができるらしいぐらいの知識しか無く、ドキュメントを開いて、コピーして、コピーしたドキュメントに対して正規表現で置換をかけてPDFに保存して電子メールで送信するなんて事ができるんだなーとわかった時は、ちょっと感動しました。Hangouts API で遊ぼうのセッションでは、Google Maps API のエキスパートの石丸さんとペアで、日頃から購読している Web OS Goodies の伊藤さんから手ほどきを受けるという、たぶん豪華なハンズオン。消化不良気味でしたが、普段は使った事のない Google Console とか使えて世界が広がった気がします。  懇親会では、江川さんと足立さんに挟まれて、江川さんには「雪明かりの路」が良いですよと、オススメしたものの、日曜日の夜に家族で小樽まで出かけたら吹雪いていて遭難しそうになりました。もし、小樽に行かれてたとしたら、ごめんなさいです。足立さんも、後から考えてみればG+で「Simeji」が買収されたという話が持ち切りだったので、もうちょっと自分の方でもピンと来てれば、もっと話が広がったかなーと反省してます。  当初 Android のハンズオンを受けようかと思っていたんですが、ここんところ仕事で Android 漬けなんで、すんません、お腹いっぱいで受ける気力が起きなかったです。どっちにしろ、WebGL のセッションだけは、どうしても興味があったので、結果は変わらなかったとは思います。WebGL は独学ではきついなぁと感じていたので、情報が聞けて凄い良かったです。  Google Maps のセッションで Fusion Tables というものがあるのは、知りませんでした。これで地図を描画できるようになったのは、何時からなんでしょうか?2010年の4月には、C++で ダイレクトに図形を描画してタイル化する PHP Extension (Closed source) を自分で作成してます。Google Maps API は使いこなせば凄いんでしょうけど、自分の会社はGISをやってて対局にあるので、ちょっと距離を置いて見てしまうところがありました。Fusion Tables は、ちょっと癪に障るから、もっと違うもん考えよっ。  心残りは、GAE のハンズオンを受けれなかった事。  抽選会では、初音ミクの「ねんどろいど」当たりましたwww。クリプトンフューチャーの皆様、ありがとうございました。  今回の貴重な資料は https://sites.google.com/site/devfestxsapporo/document にあります。  それから、ちょっと今、仕事がツボっていて書く暇がないですが、Zeemote というコントローラをもらったので、Android における Bluetooth 接続 のポストを書くかもしれません。多分、この辺に関する、まとまった情報はネット上にも無いと思います。

2012年2月3日金曜日

android における sqlite3 のスレッドによるアクセス

SQLiteOpenHelper を利用していて、IlligalStateException みたいなものに出くわしたので、スレッドによるアクセスは?データベースのインスタンスは?と、気になり、結局ソースコードを追った。ぐぐって見つけたのは、「SQLiteを使う場合の注意点」で、ここに書いてある事は概ね正しいです。  SQLiteOpenHelper.java にて SQLiteDatabase は、mDatabase というメンバ変数に保持しているので、1クラスにつき、1インスタンスしか扱えません。
データベースに対しては、読み書きを行うでしょうから、getWritableDatabase 関数をコールして、内部で保持しているデータベースのインスタンスを取得する事になります。スレッドで読取り専用であっても、データベースは、DBOpenHelperに対して、ひとつのインスタンスなのでしょうがないです。内部のコードを追っていると、DBOpenHelper::getReadableDatabase 関数の中から DBOpenHelper::getWritableDatabase をコールしている場所があるので、現時点では、あまり違いは無いかもしれません。ただし、現在どっちのモード(読取り専用かどうか)でデータベースを開いているかは、内部で管理しているみたいで、整合性が合わないと、IlligalStateException がスローされます。
カーソルを作成すると、データベースの読取領域がメモリ上に読み込まれる感じになるので、この同じデータベース・インスタンスに対して、別スレッドから同時アクセスしても、そんなに大きな問題にはならないでしょう。ただし、これが可能なのは、1つの書き手と残りは複数の読み手に限られます。書き込みトランザクション中に別スレッドから読取操作が行われながらトランザクションが完了するので、非常に気持ちの悪い動作になります。よって、常識的にコードを書くならば、スレッド1個に対してDBOpenHelperのインスタンスを1つ用意すべきでしょう。そうすれば、読取り専用と書き込みの区別もできます。
 あと、この辺の情報を検索していて、データベースを開いた状態でメンバ変数に保持する事や、カーソルを開いたままメンバ変数に保持するのは、ご法度だみたいな事を書いている人もいるみたいですが、これは間違いです。Android では、デバイスから得られる情報を取得するためのイベント・リスナ中の関数は、別スレッドになるので、ここら辺を意識できないでコードを組む人には、そのような説明をした方が都合が良いからだと思われます。