SQLiteを操作するAirアプリケーションを作成する 4(Select編)

前回でひとまずinsertまでは出来た。次にDBからデータを取得し、一覧させる様にしたい

  1. まずは画面に一覧させる受け皿を用意してやる
    <mx:DataGrid id="dg" width="100%" height="100%" dataProvider="{dp}">
      <mx:columns>
        <mx:DataGridColumn dataField="name" headerText="Name" />
        <mx:DataGridColumn dataField="height" headerText="Height" />
        <mx:DataGridColumn dataField="weight" headerText="Weight" />
        <mx:DataGridColumn dataField="bust" headerText="Bust" />
        <mx:DataGridColumn dataField="waist" headerText="Waist" />
        <mx:DataGridColumn dataField="hip" headerText="hip" />
        <mx:DataGridColumn dataField="birthday" headerText="Birthday" />
        <mx:DataGridColumn dataField="age" headerText="Age" />
      </mx:columns>
    </mx:DataGrid>
    
    細かい説明は後述
  2. 続いてコードの修正。importに下記を追加
    import mx.collections.ArrayCollection;
    
    ArrayCollectionは配列を扱うクラス。他にもArrayという似たクラスがあるが、ArrayCollectionはArrayのラッパークラスになっており、1で書いたdataProviderに利用できる。Arrayだと利用出来ないのでArrayCollectionを使う
  3. 続いてメタデータタグと変数宣言をする
    private var stmt:SQLStatement;
    
    //追加
    [Bindable]
    private var dp:ArrayCollection = new ArrayCollection();
    
    メタデータタグについてはここを参照。
  4. 続いて下記の様なfunctionを追加する
    private function get():void {
       stmt = new SQLStatement();
       stmt.sqlConnection = sqlConn;
       stmt.text = "SELECT name,height,weight,birthday,bust,waist,hip,age FROM idol";
    
       stmt.addEventListener(SQLEvent.RESULT, getDataResult);
       stmt.addEventListener(SQLErrorEvent.ERROR, errorResult);
       stmt.execute();
    }
    
    private function getDataResult(event:SQLEvent):void {
       stmt.removeEventListener(SQLEvent.RESULT, getDataResult);
       stmt.removeEventListener(SQLErrorEvent.ERROR, errorResult);
    
       var result:SQLResult = stmt.getResult();
       
       if (result.data == null){
          return;
       }
       dp = new ArrayCollection(result.data);
    }
    
    やってることは単純で、selectのSQL文を作成し、リスナーにイベントを登録。SQLを実行後、正常ならgetDataResultが呼ばれ、リスナーからイベントを削除後、dpに対してselect結果を与えている。
  5. ここでまとめと補足
    • 今回データを一覧するためにDataGridを利用した。DataGridにはdataProviderという機能があり、dataProviderに指定したArrayCollectionの内容を表示してくれる
    • 今回の場合dataProviderにdpという変数を入れているが、dpを監視し内容に変更があった場合にイベントを発行してくれる様にするのが[Bindable]というメタデータタグになる。
      DataGridはその発行されたイベントを受け取り、自動的に表示されている内容を書き換えてくれるデータバインディングという仕組みを持っている
    • DataGridのdataFieldに設定されている文字列はDBのカラム名と同一であれば正常に表示してくれる。仮にdataField="name"をdataField="name2"等にしてしまうと表示してくれない
  6. これでDBから値を取得できたので、createTableとinsertのSQL発行後に呼んでやるようにした
    stmt.execute();
    //追加
    get();
    

が、ここでちょっとわからない部分が出てきてしまった。

  • 当初、こんな感じのfunctionを作成してみた
    private function get():void {
       stmt = new SQLStatement();
       stmt.sqlConnection = sqlConn;
       stmt.text = "SELECT name,height,weight,birthday,bust,waist,hip,age FROM idol";
    
       try{
          stmt.execute();
          getDataResult();
          successResult();
       }catch(error:Error){
          errorResult(error);
       }
    }
    
    private function getDataResult():void {
       var result:SQLResult = stmt.getResult();
       
       if (result.data == null){
          return;
       }
       dp = new ArrayCollection(result.data);
    }
    
    要はイベントリスナーを利用せず、stmt.execute()後にgetDataResultを呼んでやれば同様の結果になるだろと思っていたのだが、DataGridに値が反映される事は無かった。何故だろう?