2012年09月15日

Androidのライブラリを作ってみたよ

Empressia for Androidって

Android用のライブラリを作ってみたよ。
いくつか便利なクラスを用意してあるから、紹介するね。
※Android 2.3.3(API Level 10)以上、r16以上のSupport Library v4を使ってるよ。

DBUnit

JPAみたいな@Idと@Columnのアノテーションをデータクラスにつけて、
簡単にDBのやりとりをするクラスだよ。
SQLかかなくてすむわけじゃないけど、だいぶ楽になるんじゃないかな〜。

基本的には、継承して使ってね。たとえばこんな感じ。
public class HogeDBUnit extends DBUnit {
@Override
protected Class<?>[] getManagedClasses() {
return new Class<?>[] { DataClass1.class, /* DataClass2.class, DataClass3.class */ };
}
}
public class DataClass1 {
@Id @Column
public int ID;
@Column
public String Name;
}

これで、DBUnit使うときに適当なCREATE文が自動で作られてDBが準備されるよ。
アノテーションはsetterとかにつけてもok。

データを全部取ってくる場合は
List list = this.DBUnit.findAll(DataClass1.class, null);
これで全件取得できるよ。

まぁ、JOINとかWHEREとかを書くときは、全部自力で書かないといけないんだけどね。
でもオブジェクトにマッピングするところは自動でできるよ。

SharedPreferences

Androidに用意されてるSharedPreferencesのキーってStringなんだよね。
ローカライズするものじゃないからだと思うけど、キーをリソースにしたくなったりしない?
そういう場合は、このクラス。

SharedPreferences prefs = new SharedPreferences(originalPrefs);
こんな感じでラップすればリソースをキーに使えるよ。
SharedPreferences prefs = SharedPreferencesUtilities.getPrivate(context);
ってやれば、アプリ用の設定を一発で取ってくることもできるよ。
う〜ん、微妙?
キーをリテラルで埋め込んでるよりはましかな〜って思ったんだけど。 

AbstractListAdapter

ListAdapterでなんかViewのリサイクルとか考えるのが面倒だから、AbstractListAdapterって言うのを用意してみたよ。
createViewとupdateViewをそれぞれ実装すれば良いだけだから簡単だよ。

AbstractListPagerAdapter

ViewPager用のクラスを作ってみたよ。
ViewPagerは元々、いろんな見栄えのページを切り替えるために作られたと思うんだけど、
同じ見栄えのページをListViewみたいに連続して表示したいと思うことってない?

コンストラクタで、レイアウトと表示するデータのリストを渡すと、あとは自動で切り替えとかするよ。

updateViewでViewを書き換えるだけで横に1ページごとに切り替えられるListViewのできあがり。
PagerAdateprとか、FragmentPagerAdapter、FragmentStatePagerAdapterから作るよりも
楽に作れてメモリも節約できるんじゃないかな〜。

他にもいろいろクラス入ってるので試してみてね('-^*/
Javadocもあるんだけど、なんかメモとか混入してるからほしい人がいればってことで……(゜▽、゜

posted by すふぃあ at 15:22| Comment(1) | TrackBack(0) | 雁字

2012年03月25日

DoCoMoのアプリ落ちすぎ

SPモードなメールを見るようになってからだと思うんだけど、なんかすごくDoCoMoのアプリが落ちる。
とりあえず、スタックトレースを2個拾ってみた。
ATOKの時は発生率低かったけど、こっちは簡単に起きるね(笑)

最初のやつは、黙って裏で吐いてるエラー(普通に使ってる人には見えない)。
2番目のは、強制終了したとかメッセージが出てくる。
バグレポートも送れないし、プリインストールするならもっとちゃんとしたの作ってほしいな。
2個目のは、DoCoMoじゃないのかな?

03-25 22:58:06.861: E/DatabaseUtils(32600): Writing exception to parcel
03-25 22:58:06.861: E/DatabaseUtils(32600): android.database.sqlite.SQLiteAbortException: unavailable to link the app during the startup process.
03-25 22:58:06.861: E/DatabaseUtils(32600): at jp.co.nttdocomo.carriermail.service.AppLinkProvider.h(AppLinkProvider.java:157)
03-25 22:58:06.861: E/DatabaseUtils(32600): at jp.co.nttdocomo.carriermail.service.AppLinkProvider.query(AppLinkProvider.java:371)
03-25 22:58:06.861: E/DatabaseUtils(32600): at android.content.ContentProvider$Transport.bulkQuery(ContentProvider.java:174)
03-25 22:58:06.861: E/DatabaseUtils(32600): at android.content.ContentProviderNative.onTransact(ContentProviderNative.java:111)
03-25 22:58:06.861: E/DatabaseUtils(32600): at android.os.Binder.execTransact(Binder.java:324)
03-25 22:58:06.861: E/DatabaseUtils(32600): at dalvik.system.NativeStart.run(Native Method)
03-25 22:58:09.351: E/AndroidRuntime(32621): FATAL EXCEPTION: main
03-25 22:58:09.351: E/AndroidRuntime(32621): android.database.sqlite.SQLiteException: unable to close due to unfinalised statements
03-25 22:58:09.351: E/AndroidRuntime(32621): at android.database.sqlite.SQLiteDatabase.dbclose(Native Method)
03-25 22:58:09.351: E/AndroidRuntime(32621): at android.database.sqlite.SQLiteDatabase.onAllReferencesReleased(SQLiteDatabase.java:327)
03-25 22:58:09.351: E/AndroidRuntime(32621): at android.database.sqlite.SQLiteDatabase.close(SQLiteDatabase.java:892)
03-25 22:58:09.351: E/AndroidRuntime(32621): at android.database.sqlite.SQLiteOpenHelper.close(SQLiteOpenHelper.java:220)
03-25 22:58:09.351: E/AndroidRuntime(32621): at jp.co.omronsoft.android.decoemojimanager_docomo.DBManager.close(DBManager.java:224)
03-25 22:58:09.351: E/AndroidRuntime(32621): at jp.co.omronsoft.android.decoemojimanager_docomo.DecoEmojiManager$1.handleMessage(DecoEmojiManager.java:159)
03-25 22:58:09.351: E/AndroidRuntime(32621): at android.os.Handler.dispatchMessage(Handler.java:99)
03-25 22:58:09.351: E/AndroidRuntime(32621): at android.os.Looper.loop(Looper.java:138)
03-25 22:58:09.351: E/AndroidRuntime(32621): at android.app.ActivityThread.main(ActivityThread.java:3701)
03-25 22:58:09.351: E/AndroidRuntime(32621): at java.lang.reflect.Method.invokeNative(Native Method)
03-25 22:58:09.351: E/AndroidRuntime(32621): at java.lang.reflect.Method.invoke(Method.java:507)
03-25 22:58:09.351: E/AndroidRuntime(32621): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:878)
03-25 22:58:09.351: E/AndroidRuntime(32621): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:636)
03-25 22:58:09.351: E/AndroidRuntime(32621): at dalvik.system.NativeStart.main(Native Method)
posted by すふぃあ at 23:22| Comment(1) | TrackBack(0) | 雁字

2011年12月24日

LINQがわからない

この記事はAdvent Calendar 2011のC#の24日目……のおまけ編だよ。

Advent Calendarの他の人の記事でも解説はいろいろ出てきているけど、LINQがわからないんだよね。
と言うわけで、何がわからないのかを書いてみるよ。

わからないって言うのは、使いどころって言うか、どういうときに使うのかって言うか、そんな感じ。
わたしの直感全開なので意味不明になると思うけど、いつものことなので気にしない。

とにかく使えばいいじゃんって話なのかもだけど、
よくわからないでとりあえずよさそうだから使うって言うのはどうかと思うの。
最初はそれでも、ちゃんと理解した方が良いよね。

で、LINQって調べてると、SQLっぽいのがいっぱい出てくるんだよね。
SQLってDBとかになれてる人が見るとわかりやすいのかもしれないけど、
クライアントのアプリ作ってるとDBってあまり使わない気がするの。
だから、クエリ構文?で解説されてもよくわからない……。

この記事を書くのに、メソッド構文?を中心に書いてあるneue ccさんの記事から
いくつかサイト巡ってたら、この辺にパイプライン型とかの図があってわかりやすかった。

で、
「LINQってデータコレクションを、好きなパイプラインを使ってフィルターしてくれるってことかなー」
って思うところまで来たんだけど、それで良いのかがわからない(・x・

……これを書いてる間に少しわかってきた気がするから、少し使ってみようかな?
posted by すふぃあ at 00:45| Comment(1) | TrackBack(0) | 雁字

Windows PhoneでVNC Viewerつくってみたよ

☆前書き☆

この記事はAdvent Calendar 2011のC#の24日目だよ。

去年のAdvent Calendarとかみんな凄いの書いてるから、
わたしなんか書いて良いのかな〜って思ったりもしたんだけど、
相談したら書いて良いんじゃない?って言われたので書くことにしたの。

他の人に比べて内容も読みやすさもレベルを下げてお届け!
読みにくいって思ったら、この日の記事はなかったことにして次に期待すると良いとおもいまーす。
あ、C#のコアな話を期待している人、そんな内容はないからね!

と、前書きはこのくらいにしてすすむね。
この1ヶ月くらいで作ったWindows Phoneアプリあたりの話をだらだら書くよ。

☆作ったWindows Phoneアプリの紹介☆

C#の勉強ついでにいろいろアプリ作ってみてるんだけど、
Windows Phoneを手に入れたので、せっかくだから何かつくろーって。
で、Androidで作った「ラティ」ってアプリのWindows Phone版を作ることにしたの。
VNCとかRDPとかの、いわゆるリモートデスクトップって言うののクライアントアプリだよ。

なんか、最初に作るならHello Worldでしょ!って言うのが普通なのかもしれないけど、
見た目さみしいし、やっぱりきれいで動くのがいいじゃん?

Android版はVNCベースじゃなかったから、今回は、VNCにちゃんとつながるようにしよう!
というわけでWindows Phone版の「ラティ」はTightVNCのServerとかにつながるようになってるよ。
有料のカテゴリ?になってるけど、トライアル版でも機能差は無いので普通に無料で使えるよ。

☆RFBプロトコル編☆

VNCって言うのはRFBプロトコルで通信するので、それを実装したライブラリとかがないと、だよね。
ってことで探したんだけど……、使えそうなのがないっ(・x・

というわけでRFBプロトコルの仕様書日本語)を読むところから始めることに。
リモートデスクトップのプロトコルって読み解くの大変なんじゃないのかなぁ。
な〜んて最初は思って読んでみたんだけど、これが意外に凄い簡単なの。
FTPのプロトコル日本語)よりも簡単簡単。たぶん。

最初はなんか文字列の送受信するだけで、あとは、
位置+サイズ+画像のデータをひたすら受け取るだけだよ。ほら簡単。

いろいろ手抜き感はあるけど、実装したライブラリがあるので後でリンク張るね。
ここでは簡単に使い方を紹介するよ。

基本的なプロトコルの実装は、RFBStreamって言うのがあるから、それを使えばおっけ。
でもほら、接続から一連のパスワード確認とかは、まとめてやった方が楽じゃない?
というわけでRFBClientってクラスもあるよ。
でもでも、それでももっと簡単に使いたいって人のために、EmprssiaRFBClientって言うのも用意してみた〜。
今回はこれの紹介ってことで。

えーっと、ラティから抜粋したコードをブログ用に書き換えてるので動作保証はないでーす。
あ、もちろん、書き換えて無くても動作保証はないけど。

コーディングスタイルがあり得ない!って言うのはスルーするけど、
LINQとかRxとかAsyncはぜ〜んぜん使えてないのだ。
せっかくAsync CTP入れたのにね!(謎)

this.RFBClient = new EmpressiaRFBClient();
int[] encodings = new int[] { EncodingType.tight, EncodingType.ZRLE, EncodingType.zlib, EncodingType.zlibhex, EncodingType.CoRRE, EncodingType.RRE, EncodingType.Raw, EncodingType.Hextile, EncodingType.Cursor };

// 1.セットアップでいろいろ準備。
this.RFBClient.setup(
// 1−1.使う通信方式(エンコーディング)の設定。
encodings,
// 1−2.カーソルをクライアントで描画する。
(PixelFormat, x, y, width, height, pixelBytes, maskBytes) => {
}
// 1−3.EncodingType.CopyRectを使用する場合はもう一個引数増える。
);
this.RFBClient.ConnectFailed += (sender, e) => {
if(e.IsCanceled) {
return;
}
string message = null;
if(e.SecurityResult != null) {
if(e.SecurityResult.FailedReason != null) {
message = e.SecurityResult.FailedReason;
}
}
if(message == null) {
if(e.UnexpectedException != null) {
message = e.UnexpectedException.Message;
} else {
message = "なんか接続に失敗したみたい。ごめんなさい。理由はよくわかんない。";
}
}
this.RaiseDisconnected(message);
};
this.RFBClient.SendFailed += (ex) => {
this.RaiseDisconnected(ex.Message);
};
this.RFBClient.ReceiveFailed += (ex) => {
this.RaiseDisconnected(ex.Message);
};
this.RFBClient.FrameBufferInitialized += (PixelFormat, width, height) => {
// 2.画面情報の初期化。
AutoResetEvent Lock = new AutoResetEvent(false);
this.Dispatcher.BeginInvoke((EmpressiaRFBClient.FrameBufferInitializedHandler)delegate {
// 2−1.Windows PhoneだとARGB32が楽。違う場合は要求を送信するよ。
PixelFormat ARGB32 = new PixelFormat() {
BitsPerPixel = 32,
Depth = 24,
BigEndianFlag = 0,
TrueColourFlag = 1,
RedMax = 255,
GreenMax = 255,
BlueMax = 255,
RedShift = 16,
GreenShift = 8,
BlueShift = 0,
Padding1 = 0,
Padding2 = 0,
Padding3 = 0,
};
if(PixelFormat.Equals(ARGB32) == false) {
this.RFBClient.sendSetPixelFormat(ARGB32);
}
this.Image = new WriteableBitmap(this.RFBClient.FrameBufferWidth, this.RFBClient.FrameBufferHeight);
Lock.Set();
}, PixelFormat, width, height);
Lock.WaitOne();
};
this.RFBClient.MessageReceivingStarted += () => {
// 3.初回だけリクエストのタイミングを決める。2回目以降は勝手に呼ばれる。
this.RFBClient.sendFramebufferUpdateRequest(true, 0, 0, this.RFBClient.FrameBufferWidth, this.RFBClient.FrameBufferHeight);
};
this.RFBClient.ImageReceived += (s, rects) => {
lock(this.ImageEventLock) {
this.ImageLock.Reset();
this.Dispatcher.BeginInvoke((EmpressiaRFBClient.ImageReceivedHandler)delegate {
foreach(RFBRectangle rect in rects) {
// 4.透明なのを塗りつぶすよ。
for(int i = 3; i < rect.PixelBytes.Length; i += 4) {
rect.PixelBytes[i] = 0xFF;
}
for(int lineIndex = 0; lineIndex < rect.Height; ++lineIndex) {
Buffer.BlockCopy(rect.PixelBytes, lineIndex * rect.Stride, this.Image.Pixels, (rect.Y + lineIndex) * this.Image.PixelWidth * 4 + rect.X * 4, rect.Stride);
}
}
this.Image.Invalidate();
this.ImageLock.Set();
}, s, rects);
this.ImageLock.WaitOne();
}
};

this.RFBClient.connectAsync(Host, Port, Password);

重要そうなところは1〜4の番号を振ってコメント入れておいたっ。
1−2と1−3:
特殊な画像処理が必要なところ(クライアントの描画環境によるからRFBの範囲ではどうしようもない)。
2−1:
Windows PhoneのWriteableBitmapがARGB32(BGRA32?)だから楽するための処理ね。
わたしの作ったライブラリの一部がそれ前提なところが残ってる気もするし。
3:
コメント書いてて、これライブラリとしてダメじゃないカナーとか思った!
思ったけど今はこうなってるからいいよね(゚ー゚)(。_。)(゚-゚)(。_。)ウンウン
4:
RFBプロトコルは、透明度扱わないんだけど、
WriteableBitmapのARGB32だとアルファチャンネルってことになっちゃうから、
全部透過なしに上書きしてる。

あとは、xaml側と調整すれば画面が出るはず〜。
キー送信とか、マウスの操作は、
sendKeyEventとsendPointerEventっていうメソッドがあるから画面の操作と連携させればおっけ〜。
KeyEventは結構大変だけどねっ。マウス操作くらいならすぐすぐ。

是非試してみてね(  ̄▽ ̄)ノ

☆SSHプロトコル編☆

RFBプロトコルってパスワード部分をのぞけば暗号化されないから、
SSHでポートフォワードとかやりたいよね。
というか、Empressia Tunnelなんて作ってたから、
簡単にできるでしょ〜って思って、手を出してみたの。
まぁ、つまり大変でしたって話なんだけど……。

C#でSSHと言えば、SharpSSHとかが有名……だよね、
うん、わたしが知ってるくらいだから有名なの。
その、SharpSSH使おうと思ったんだけど、
これってJavaのJSchっていうライブラリの移植版みたいなんだよね。
元が結構古くて.NEtFramework1.1ベースみたい。

ってことで、ArrayListとかHashtableとかがWindows Phoneだと動かない。
Threadとかのメソッドも減って消えてるメソッドがあるからそのままじゃ使えないし。
BigIntegerもMono?のを使ってるみたいでこれがunsafeコードを持ってるんだよね。
結局、いろんなところ書き換えちゃった。

ほんとはそのまま動くようにするだけで良いんだろうけど、
元がJavaだからか、プロパティとかイベントとかがほとんど使われてなかったから、
めんどくさくて適当に書き換えちゃったところも。

RFBと同じでライブラリは最後にまとめて張るね。
まぁ、ポートフォワード付近しかタメしてなかったりするから、いろいろなところでエラーとか出るかも(笑)

あ、おまけでEmpressiaSSHなんてライブラリも作ったよ。
このライブラリを使うと、SECSH(ssh.com)形式の秘密鍵ファイルが使えるようになるの。
あと、ポートフォワードが簡単に使えるクラスEmpressiaSSHTunnelClientも用意してあるのでお試しアレ。
RFBみたいに使い方を紹介するよ。
もちろん動かなくても知らない!さすがわたし!無責任!

EmpressiaSSHTunnelClient SSHTunnelClient = new EmpressiaSSHTunnelClient();
userInfo.FingerprintConfirmationRequired += (string host, string type, string fingerprint) => {
return true;
};
userInfo.ChangedFingerprintConfirmationRequired += (string host, string type, string fingerprint) => {
return true;
};
SSHTunnelClient.Connected += delegate {
// 接続したよ。
};
SSHTunnelClient.Bound += delegate {
// ポートフォワードが開始されたよ。
};
SSHTunnelClient.ConnectionFailed += delegate {
// 接続に失敗したよ。
};
SSHTunnelClient.Disconnected += delegate {
// 切断されたよ。
};
SSHTunnelClient.Unbound += delegate {
// ポートフォワードが終わったよ。
};
EmpressiaUserInfo userInfo = new EmpressiaUserInfo("sshpassword");
SSHTunnelClient.connectAsync(new TransferProfile() {
TunnelHost = "example.com",
TunnelPort = 22,
TunnelUser = "sshuser",
TunnelPassword = "sshpassword",
LocalHost = "127.0.0.1",
LocalPort = 5900,
RemoteHost = "192.168.0.2",
RemotePort = 5900,
}, userInfo, null);
なんか、パスワード2回指定してるけど気にしない!

でもさ、結局、Windows PhoneってSocketのAcceptできないんだよね。
というわけでローカルポートにバインドできなくて今回はあきらめたっ_(__)ノ彡☆

あ、あと、SilverlightとWindows Phoneだと、SshShellのコンソールリダイレクトが使えないはず。
Console.OpenStandardInput()とConsole.OpenStandardOutput()をどうすればいいのかがわからなくて……。

☆基本ライブラリ編☆

SSHとかRFBをWindows Phoneで作る時に思ったんだけど、
Windows Phoneって結構標準のクラスライブラリが削られてて面倒なんだよね。
暗号系はBouncy Castleあたりがあれば良いんだけど、ネットワーク関連がどうしようもなくて……。
ってことで、NetworkStreamとか作ってみてるよ。
パフォーマンスは微妙だと思うけど、だいたい同じ感じで使えるはず……。

あと、リングバッファなByteQueueとか、
それをストリームで扱うEndlessStreamなんかもあるので良ければドーゾ。

EmpressiaLibrary.dllにまとめて入れてあるので興味があれば〜。
ライブラリはまたまた最後にまとめて張っておくね。

使い方は、別に特殊なのはないので省略ね。
……みんなはこういうのどうしてるんだろう……?(・_・?)ハテ

☆その他ライブラリ編☆

RFBやってると、ZlibなStreamを延々読み続けないといけないんだよね。
ただ1個のストリーム読むだけなら良いんだけど、
飛び飛びにあるピクセルデータ部分だけを連続したZlibなStreamとして扱わないとダメって感じ。
標準クラスライブラリのDeflateStreamを使ってる分には問題ないんだけど、
DotNetZipのDeflateStreamだと、これがうまく動かないっ。
というわけでこれも書き換えてみたよ。
まぁ、使う機会はほとんどないと思うけど、後で張っておくね!

Bouncy CastleもWindows Phoneで動くように書き換えたのでこれも張っておくよ。

☆ライブラリまとめ☆

ず〜っとライブラリの話書いてきたけど、下に関連してる図を載せておくね。
EmpressiaLibraryDependencyGraph_20111224.png
であとは、ライブラリ達でーす。

えっと、Silverlight版は、プロジェクトファイル用意するだけなんだけど、
わたしが使う予定がないので用意してなかったり!

動かないじゃんっていうのがあれば、再現できるサンプルとかあればがんばるよ!たぶん(・x・

☆余談☆

ところで、Vita用のSDKが来ないんだけど……。
って書こうと思ったら、昨日(23日)の15時頃に連絡があったよ。
やっと、開発環境周りの日本語訳ができたのかな〜。
というわけでPS Suite SDKダウンロードしてみた。
まだ何も作ってないけど、なんか作りにくそうだった……(・x・

タグ:Windows Phone
posted by すふぃあ at 00:34| Comment(4) | TrackBack(1) | 雁字

2011年12月08日

Windows Phone 7で暗号化

えっと、なんか、WP7の暗号化っていろいろ足りなかったりするよね。

たぶん、Phone7.FxとかBouncy Castleとかいろいろあるから、
何でも使えば良いんだと想うんだけど、

#wp7dev_jpで困っている人がいるみたいだったので、
とりあえず、Bouncy CastleをWP7で動くようにビルドしたのをおいてみたよ('-^*/

もちろん、ライセンスは、元の方を見て使ってね。
http://www.bouncycastle.org/
一応ビルドしたのはここね(゜▽、゜
http://www.empressia.jp/dll/BouncyCastle.Empressia.WindowsPhone.dll

こういうのはダメなんだよ!ってことはないとおもってるけど、
そういう情報があったら教えてね。速攻消すから。
あと、WP7で使っておかしくなっても、元の方に文句言わないでね。
タグ:Windows Phone
posted by すふぃあ at 23:09| Comment(1) | TrackBack(0) | 雁字

2011年10月30日

Windows PhoneのISEToolのGUIアプリ

Windows Phone OS 7.1 あたりで出てきたISEToolがCUIなので、
GUIで操作できるアプリを作ってみたよ。一通り必要な機能は入れたつもり。
この辺からダウンロードできるよ

リモートの表示がちょっと遅いんだよねぇ。階層が深ければ深いほど。
必要なときに読み込むようにしてあげた方が良いのかなぁ。
タグ:Windows Phone
posted by すふぃあ at 15:13| Comment(3) | TrackBack(0) | 雁字

2011年09月03日

MMDX(SlimDX版)のモデルロードを高速化

何となくぼーっと、MMDXを触ってみているよ。


Lat式ミクVer2.3を歩かせてみてるんだけど、ロード時間が長いので、ライブラリの速度アップをしてみました。


ここのリンクからダウンロードできるよ。


わたしのPC上でだけど、Lat式ミクVer2.3のロード時間が12秒→3秒くらいになた(゜▽、゜快適
タグ:MMD MMDX
posted by すふぃあ at 01:08| Comment(1) | TrackBack(0) | 雁字

2011年07月18日

WeldからJSFのViewScopedが使えるようになったみたい

Weld(CDI)とMojarra(JSF)の連携がGlassFish v3.1あたりで強化されているみたいなので確認してみたよ。



GlassFish v3のころは、連携が十分じゃなかったんだよね。

具体的には、@ManagedBeanに対して、@Injectが動かなかったの。

でも今は動くようになってる。




比較していくと、普通にWeld(CDI)の場合はこんな感じ。

テキストエディタで書いてるから間違ってたらごめんなさい。



@javax.inject.Named

@javax.enterprise.context.RequestScoped

public class HogeComponent {

  // CDIとしてDIされる。

  @javax.inject.Inject

  PiyoComponent piyo;

}


これでCDI管理の元で、Injectされる。

で、今までMojarra(JSF)で同じことやろうとすると、こんな感じ。


@javax.faces.bean.ManagedBean

@javax.faces.bean.ViewScoped

public class HogeComponent {

  // JSFとしてDIされる。

  @javax.faces.bean.ManagedProperty

  PiyoComponent piyo;

}

@Injectが使えなかったってこと。


ManagedBeanだと、CDI管理下に入らないから、

CDIがInjectするための@Injectが動かなかったんだと思う。


Weldの良いところは、なんでも@Injectで入れちゃうぞ、っていうことだから、

『ManagedBeanの方使わなければいいじゃん。』っていう話でもあったんだけど、

そうすると、ViewScopedが使えなくなるという……。



下のようなのは動かないってこと。



@javax.inject.Named

@javax.faces.bean.ViewScoped

public class HogeComponent {

  // GlassFish v3では動かない。

  @javax.inject.Inject

  PiyoComponent piyo;

}

このために、Weldで動くViewScopedを自作するというのをやってたんだけど、

GlassFish v3.1に載ってるWeldさんならそんな必要もなくなったみたい。

結局、下のでCDI管理下に入るようになったのかな。



@javax.faces.bean.ManagedBean

@javax.faces.bean.ViewScoped

public class HogeComponent {

  // GlassFish v3.1では動く。

  @javax.inject.Inject

  PiyoComponent piyo;

}

これで、Injectがちゃんとされる。JSF全体がCDI管理下に入った感じかな。

もうオリジナルなViewScopedはいらないね('-^*/


タグ:Weld CDI ViewScoped
posted by すふぃあ at 10:36| Comment(2) | TrackBack(0) | 雁字

2011年05月13日

AndroidのATOKでエラー やっとスタックトレース捕まえたよ

別にデバッグしたかった訳じゃないんだけど、Android版ATOKがなかなか更新がないので張ってみる。

激しく色々リークしてそうな……(゜▽、゜

今日バージョン上がったみたいだけど直ってないとおもうんだよねー。

裏の見えないところで色々リークしてそうだねー。



ERROR/Database(2392): Leak found

ERROR/Database(2392): java.lang.IllegalStateException: /data/data/com.justsystems.atokmobile.trial.sifications.db SQLiteDatabase created and never closed

ERROR/Database(2392): at android.database.sqlite.SQLiteDatabase.(SQLiteDatabase.java:1695)


ERROR/Database(2392): at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java

ERROR/Database(2392): at android.database.sqlite.SQLiteDatabase.openOrCreateDatabase(SQLiteDatab

ERROR/Database(2392): at android.database.sqlite.SQLiteDatabase.openOrCreateDatabase(SQLiteDatab

ERROR/Database(2392): at android.app.ApplicationContext.openOrCreateDatabase(ApplicationContext.

ERROR/Database(2392): at android.content.ContextWrapper.openOrCreateDatabase(ContextWrapper.java

ERROR/Database(2392): at android.database.sqlite.SQLiteOpenHelper.getWritableDatabase(SQLiteOpen

ERROR/Database(2392): at android.database.sqlite.SQLiteOpenHelper.getReadableDatabase(SQLiteOpen

ERROR/Database(2392): at com.justsystems.atokmobile.trial.common.c.a(Unknown Source)

ERROR/Database(2392): at com.justsystems.atokmobile.trial.service.AtokInputMethodService.onStart)

ERROR/Database(2392): at android.inputmethodservice.InputMethodService.doStartInput(InputMethodS

ERROR/Database(2392): at android.inputmethodservice.InputMethodService$InputMethodImpl.startInpu.java:354)

ERROR/Database(2392): at android.inputmethodservice.IInputMethodWrapper.executeMessage(IInputMet

ERROR/Database(2392): at com.android.internal.os.HandlerCaller$MyHandler.handleMessage(HandlerCa

ERROR/Database(2392): at android.os.Handler.dispatchMessage(Handler.java:99)

ERROR/Database(2392): at android.os.Looper.loop(Looper.java:123)

ERROR/Database(2392): at android.app.ActivityThread.main(ActivityThread.java:4370)

ERROR/Database(2392): at java.lang.reflect.Method.invokeNative(Native Method)

ERROR/Database(2392): at java.lang.reflect.Method.invoke(Method.java:521)

ERROR/Database(2392): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.j

ERROR/Database(2392): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:626)

ERROR/Database(2392): at dalvik.system.NativeStart.main(Native Method)
タグ:android
posted by すふぃあ at 21:04| Comment(2) | TrackBack(1) | 雁字

2011年05月02日

もしわたしがAndroidのFragmentを使ったら


さて、だいぶ更新あいちゃったけど、

Fragment APIを一通り使ってみたので、書いてみようと思うの。

いつものように、普通のその辺のチュートリアル記事とかじゃおもしろくないので、

わざとそれとは違うことを書くですよ。




まず、よく見るのは、Fragment使うと、UIがとっても便利!みたいな話だよね。

これは、たしかにタブレットなAndroidで重要で、そのためにFragmentが作られたみたいだし間違ってはいない……気がする。

でも……、見た目ばかり先行しちゃって、重要なことが本当に理解はされていないと思うんだよね。

つまりね、一番重要なのは、「ライフサイクル動作までの単位で再利用を可能にしたこと」だと思うの。




Dialogを例にしてみるよ。

今まで(Fragment APIが出るまで)は、Dialogは拡張できたけど、そのライフサイクル依存な動作は、Activityに書くしかなかったよね。

えっと、onResumeで決まった動作をするDialogとか作りたくても、その部分だけは、Activityに記述するしかなかったの。

同じような処理をいろんなアクティビティでやりたければ、Activityごとに全部書かないといけなかったってこと。

これはとっても再利用しにくいよね。




で、Fragmentがあるとどうなるかっていうと。

Fragmentにもライフサイクル機能があるから、onResumeでのその決まった動作は、ActivityじゃなくてFragmentの方にかける。

ってことは、Activityにはそのコードがなくなる。つまり、Activityごとに書いてた処理が一つのFragmentに寄せられるってわけ。

ライフサイクルのプラグインって感じね。まぁ、実際コード見ると、ActivityのonResumeで、FragmentのonResumeが呼ばれているわけだけど(笑)

これで、必要なコードは一カ所にまとめられて再利用しやすくなるの。




あ、そうそう、注意点があるよ。

あくまでもこれは、Activityに寄せられてたライフサイクルの記述をFragmentと言う単位に切り出せるようになっただけ。

よくListViewがListFragmentになるように見られることがあるみたいだけど(、まぁ、それは間違っていないんだけど)、

実際には、Activityに書かれてたコードがFragmentに寄るだけで、UIをカスタマイズしたらそのコードはFragmentとは別に用意することになる。

「Activity→Fragment→View」ってなるかな。クラスはFragmentの分増えるってこと。

間違えないようにしないとね。




もう一個重要なのは、上に書いたことから、ViewがないFragmentも作れるってこと。

ライフサイクルに沿ったバックグラウンド処理とかが、Acitivityから切り離したと言う意味で再利用可能な形で作れるってことだよ。

むしろ今は、こっちの方が重要な気がする(笑)




何でかっていうと、Fragment、なんかアニメーションがおかしいんだよね。

普通に設計ミス?みたいな感じがしてるけど(笑)

一応、「Android Issue 15623」あたりでググれば出てくると思うよ♪




適当にやってきた感じをまとめると以下のような感じかなー。あくまで個人的な感覚だからね〜(゜▽、゜

1.ダイアログ表示は積極的にDialogFragmentを使うようにする。

2.ListViewはライフサイクル制御が必要なときだけFragmentにすればok無駄にFragmentにする必要はない。

3.ライフサイクルに依存したバックグラウンド処理はFragment使うといい感じ。

4.アニメーションしたいなら、Issue 15623あたりに注意する。


タグ:android
posted by すふぃあ at 14:17| Comment(1) | TrackBack(0) | 雁字