Archive for 2009/7/1
さて、DataGridのdataProviderを自作する件のpart2であるが、
そもそもDataGridとdataProviderはどのようなやりとりをしてデータを表示しているのだろうか?ということを書きたいと思います。
というのも、DataGridに関する情報をみていると雑誌(たぶん)などでも大きなデータでスクロールバーを動きをみて、ページング対応が必要とか記述してある。
ほんとにこんなに難しいのだろうか?と疑問に思ったのがきっかけだ。
(今回は sqlは関係ありませんが、中身がわかればどのようなクエリを発行すればいいか分かるので、参考になると思います。)
確かに、データ取得(バックエンドの都合)によるページングは必要かもしれないが、UIの動きはまったく関係なく解決できるはずだ。
Flex側の都合ではいらないのではないだろうか?ということを思った。
まあ、私もJavaのSwingや、EclipseのRCPを作った時にこのへんは勉強したなー。
(利用者がそれを知った上で、ページングをUIに望んでいるなら別ですが・・・
たまにいるんですよね。俺がほしいデータは500ページあたりにあるんだよってことが分かるくらいにつかいこんじゃう職人が・・・)
話はもどって、DataGridとdataProviderではどのようなやりとりが行われているのか、わかりやすいように会話風にしてみました。
登場人物は
UI君 :DataGridそのもの
プロバイダさん :ICollecitonViewを実装したクラス(例:ArrayCollection)
下請け :IListを実装したクラス ( 例: ArrayList ※クラスはpublicですが、ドキュメントは@private なので見えません)
神(ユーザ) :利用する人。UI君を雲の上から操作し、すごくわがままなこともできる。
では・・・
[UI君] : さっそく、データを表示したいんだけど、全部で何件あるの?
[プロバイダさん]: 下請けさん、何件なの?
[下請け] : プロバイダ様、1000万件です。( get length() )
[プロバイダさん]: 全部で1000万件だよ。 ( get length() )
[UI君] : 1件目ちょうだい!
[プロバイダさん]: はいよ、下請けさんお願いね。
[下請け] : できました。お願いします。( getItemAt() )
[プロバイダさん]: できましたよ。UI君。
[UI君] : じゃ、次2件目!
[プロバイダさん]: はいよ、例のごとくよろしく。
[下請け] : できました。お願いします。
(これが続く。。。)
[UI君] : じゃ、15件目!
[プロバイダさん]: はいよ、またお願い。
[下請け] : できました。お願いします。
[プロバイダさん]: できましたよ。UI君。
[UI君] : おっと、表示するのは15件だからこれで終わりだな。
[神(ユーザ)] : スクロールバーを下げるから、もっと下を見せなさい。
[UI君] : おー、次の仕事を頼むぞ。プロバイダさん。次16件目
[プロバイダさん]: はいよ
[下請け] : できました。お願いします。
[UI君] : 次17件目
[プロバイダさん]: はいよ
[下請け] : できました。お願いします。
[神(ユーザ)] : こりゃ、だめだ。みつからん。逆から見てみよう。ソート!
[UI君] : あちゃー、今までデータを順番にもらっていたけど。無駄だったよ。今までのお願いはなしね。
[プロバイダさん]: りふれーしゅ!!
※ ここは自作が必要ですが・・・ 、どうやらこの処理で IList のtoArray()が動くようです。
このメソッドがインターフェースに入っていなければ、IListもっと良くなると思うのですが。
これじゃ、データをすべてArrayで返さなければいけないみたいですよね。上の例だと1000万件も。
でも、実際はこの処理をすべて自作してしまえば、このメソッドは使われない(今のところ)ので、実装ではエラーでも返しちゃいましょ。
(これでほかの場所でも実は使っているのですが、そこがわかりますよ。)
[UI君] : そうそう、ソートの条件はこれね。これからもよろしく。
[プロバイダさん]: 了解!( set sort )
※ プロバイダを自作した場合にいは、ソートの概念の実装も自作が必要です。
フィールド名と順番(ASC,DES)が来るから、DBを使っていればその条件を渡してあげればいいだけですが・・・
このあたりは、下請けさんにもソートの条件を伝える必要がありそうです。
というのも、下請けさんは公式にはソート条件をもらうすべを持っていません。こっそり教えてあげましょう。
[UI君] : じゃ、1件目ちょうだい。
[プロバイダさん]: はいよ。
[下請け] : できました。お願いします。
だけど、プロバイダさんとUI君は実はもっと愛情を注げば(拡張すれば)、もっと賢くなれるようなのです。
こんな感じです。
[UI君] : 次の18件目ちょうだい。
[プロバイダさん]: 了解。じゃ、下請けよろしく。
[下請け] : ただいま、データが用意されていませんので、少々お待ちいただけないでしょうか?
[プロバイダさん]: あちゃー、それは今用意できていないよ。そんな急に言われても困るよ。UI君。( throw ItemPendingError )
[UI君] : んー、それじゃデータが用意できたら教えてよ。
時間がながれる・・・・
[下請け] : データができましたので、お知らせ致しました。
[プロバイダさん]: UI君、待たせたね。できたよ。
[UI君] : おー、ありがとう。じゃ、表示させてもらうよ。
でも、このあたりはインターフェースだけあるようで、実装はありません。
私も今のところ必要性を感じないので見ていませんのでご了承ください。
さてさて、このようにUIとプロバイダではデータが大きくなっても対応できるようなつくりになっています。
あとは、プロバイダがどのようにデータを取得するかは 下請け(IList)の実装にかかっているのです。
下請け(IList)が必要な時に1件、1件取ってきてもsqliteを使っていれば問題ないようにも思いますし、
ネットワーク越しに前もってまとめてデータを取得しておいて1件、1件渡せば、処理はページング処理(キャッシュ処理)が必要になります。
ただ、ページング処理をしてしまうと、ページアウト処理(というか、作ったデータをいらないので消す処理)が必要になってしまいます。
(このあたりは、調べきっていませんが、IViewCursorあたりがそんな役目をするためのもののような気がします。)
でも、DataGridとしてUI側の対応は何も変わらなくても問題ないということがわかっていただけるのではないでしょうか?
追記
それでも、DataGridで大きなデータを扱うときにバックエンド側や、データ自体の問題ではなくUI側の問題で対応が必要な情報をおもちでしたら、
教えていただけないでしょうか?
いずれ、私もその問題にぶつかると思いますので助かります。


