Xamarin.Android での CursorAdapters の使用
Android には、SQLite データベース クエリからのデータを詳細に表示するためのアダプター クラスが用意されています。
SimpleCursorAdapter – サブクラス化せずに使用できるため、ArrayAdapter
に似ています。 コンストラクターに必要なパラメーター (カーソルやレイアウト情報など) を指定し、ListView
に割り当てるだけです。
CursorAdapter – レイアウト コントロールへのデータ値のバインドをより詳細に制御する必要がある場合に継承できる基本クラス (コントロールの非表示/表示、プロパティの変更など)。
カーソル アダプターには、SQLite に格納されているデータの長いリストをスクロールするためのフォーマンスの高い方法が用意されています。 使用するコードでは、Cursor
オブジェクトで SQL クエリを定義し、各行のビューを作成して設定する方法を記述しておく必要があります。
SQLite データベースの作成
カーソル アダプターの実証には、単純な SQLite データベースの実装が必要です。 SimpleCursorTableAdapter/VegetableDatabase.cs のコードには、テーブルを作成してデータを設定するコードと SQL が含まれています。
完全な VegetableDatabase
クラスを次に示します。
class VegetableDatabase : SQLiteOpenHelper {
public static readonly string create_table_sql =
"CREATE TABLE [vegetables] ([_id] INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL UNIQUE, [name] TEXT NOT NULL UNIQUE)";
public static readonly string DatabaseName = "vegetables.db";
public static readonly int DatabaseVersion = 1;
public VegetableDatabase(Context context) : base(context, DatabaseName, null, DatabaseVersion) { }
public override void OnCreate(SQLiteDatabase db)
{
db.ExecSQL(create_table_sql);
// seed with data
db.ExecSQL("INSERT INTO vegetables (name) VALUES ('Vegetables')");
db.ExecSQL("INSERT INTO vegetables (name) VALUES ('Fruits')");
db.ExecSQL("INSERT INTO vegetables (name) VALUES ('Flower Buds')");
db.ExecSQL("INSERT INTO vegetables (name) VALUES ('Legumes')");
db.ExecSQL("INSERT INTO vegetables (name) VALUES ('Bulbs')");
db.ExecSQL("INSERT INTO vegetables (name) VALUES ('Tubers')");
}
public override void OnUpgrade(SQLiteDatabase db, int oldVersion, int newVersion)
{ // not required until second version :)
throw new NotImplementedException();
}
}
VegetableDatabase
クラスは、HomeScreen
アクティビティの OnCreate
メソッドでインスタンス化されます。 SQLiteOpenHelper
基底クラスはデータベース ファイルの設定を管理し、その OnCreate
メソッドで SQL が 1 回だけ実行されるようにします。 このクラスは、次の SimpleCursorAdapter
と CursorAdapter
の 2 つの例で使用されます。
カーソルクエリには、CursorAdapter
を機能させるための整数列 _id
が含まれる必要があります。 基になるテーブルに _id
という名前の整数列がない場合は、カーソルを構成する RawQuery
内の別の一意の整数に対して列の別名を使用します。 詳細については、Android のドキュメントを参照してください。
カーソルの作成
この例では、RawQuery
を使用して SQL クエリを Cursor
オブジェクトに変換します。 カーソルから返される列のリストは、カーソル アダプターに表示できるデータ列を定義します。 SimpleCursorTableAdapter/HomeScreen.cs OnCreate
メソッドでデータベースを作成するコードを次に示します。
vdb = new VegetableDatabase(this);
cursor = vdb.ReadableDatabase.RawQuery("SELECT * FROM vegetables", null); // cursor query
StartManagingCursor(cursor);
// use either SimpleCursorAdapter or CursorAdapter subclass here!
StartManagingCursor
を呼び出すコードでは、StopManagingCursor
も呼び出す必要があります。 例では、OnCreate
を使用して開始し、OnDestroy
でカーソルを閉じています。 OnDestroy
メソッドには、次のコードが含まれています。
StopManagingCursor(cursor);
cursor.Close();
アプリケーションで SQLite データベースを使用でき、以下に示すようにカーソル オブジェクトを作成したら、SimpleCursorAdapter
または CusorAdapter
のサブクラスを使用して ListView
に行を表示できます。
SimpleCursorAdapter の使用
SimpleCursorAdapter
は ArrayAdapter
に似ていますが、SQLite での使用に特化しています。 サブクラス化は必要ありません。オブジェクトの作成時にいくつかの単純なパラメーターを設定し、それを ListView
の Adapter
プロパティに割り当てるだけです。
SimpleCursorAdapter コンストラクターのパラメーターは次のとおりです。
Context – 含まれるアクティビティへの参照。
Layout – 使用する行ビューのリソース ID。
ICursor – 表示するデータの SQLite クエリを含むカーソル。
文字列の配列から - カーソル内の列の名前に対応する文字列の配列。
文字列の配列へ - 行レイアウトのコントロールに対応するレイアウト ID の配列。 from
配列で指定された列の値は、同じインデックスでこの配列で指定された ControlID にバインドされます。
from
配列と to
配列は、データ ソースからビュー内のレイアウト コントロールへのマッピングを形成するため、同じ数のエントリを持つ必要があります。
SimpleCursorTableAdapter/HomeScreen.cs サンプル コードは、次のように SimpleCursorAdapter
を接続します。
// which columns map to which layout controls
string[] fromColumns = new string[] {"name"};
int[] toControlIDs = new int[] {Android.Resource.Id.Text1};
// use a SimpleCursorAdapter
listView.Adapter = new SimpleCursorAdapter (this, Android.Resource.Layout.SimpleListItem1, cursor,
fromColumns,
toControlIDs);
SimpleCursorAdapter
は、ListView
で SQLite データを表示するための高速かつ簡単な方法です。 主な制限は、列の値をバインドしてコントロールを表示できることだけであり、行レイアウトの他の側面 (コントロールの表示/非表示、プロパティの変更など) を変更することはできません。
CursorAdapter のサブクラス化
CursorAdapter
サブクラスには SQLite からのデータを表示するための SimpleCursorAdapter
と同じパフォーマンス上の利点がありますが、各行ビューの作成とレイアウトを完全に制御することもできます。 CursorAdapter
の実装は、GetView
、GetItemId
、Count
、this[]
インデクサーをオーバーライドしないため、BaseAdapter
のサブクラス化とは大きく異なります。
動作する SQLite データベースの場合、CursorAdapter
サブクラスを作成するには、次の 2 つのメソッドのみをオーバーライドする必要があります。
BindView – ビューを指定した場合は、指定されたカーソルにデータを表示するようにビューを更新します。
NewView –
ListView
で新しいビューを表示する必要がある場合に呼び出されます。CursorAdapter
はビューのリサイクルを処理します (通常のアダプターでのGetView
メソッドとは異なります)。
前の例のアダプター サブクラスには、行数を返すメソッドと、現在の項目を取得するメソッドがあります。情報は、カーソル自体から収集できるため、CursorAdapter
でこれらのメソッドは必要ありません。 各ビューの作成と設定をこれら 2 つのメソッドに分割することで、CursorAdapter
で強制的にビューが再利用されます。 これは、BaseAdapter.GetView
メソッドの convertView
パラメーターを無視できる通常のアダプターとは対照的です。
CursorAdapter の実装
CursorTableAdapter/HomeScreenCursorAdapter.cs のコードには、CursorAdapter
サブクラスが含まれています。 また、NewView
メソッドで LayoutInflater
にアクセスできるように、コンストラクターに渡されたコンテキスト参照が格納されます。 完全なクラスは次のようになります。
public class HomeScreenCursorAdapter : CursorAdapter {
Activity context;
public HomeScreenCursorAdapter(Activity context, ICursor c)
: base(context, c)
{
this.context = context;
}
public override void BindView(View view, Context context, ICursor cursor)
{
var textView = view.FindViewById<TextView>(Android.Resource.Id.Text1);
textView.Text = cursor.GetString(1); // 'name' is column 1 in the cursor query
}
public override View NewView(Context context, ICursor cursor, ViewGroup parent)
{
return this.context.LayoutInflater.Inflate(Android.Resource.Layout.SimpleListItem1, parent, false);
}
}
CursorAdapter の割り当て
ListView
を表示する Activity
では、カーソル CursorAdapter
を作成し、リスト ビューに割り当てます。
CursorTableAdapter/HomeScreen.cs OnCreate
メソッドでこのアクションを実行するコードを次に示します。
// create the cursor
vdb = new VegetableDatabase(this);
cursor = vdb.ReadableDatabase.RawQuery("SELECT * FROM vegetables", null);
StartManagingCursor(cursor);
// create the CursorAdapter
listView.Adapter = (IListAdapter)new HomeScreenCursorAdapter(this, cursor, false);
OnDestroy
メソッドには、前に説明した StopManagingCursor
メソッド呼び出しが含まれています。