SQLiteのカーソルをうまいこと使えないものかと思った件
実際はCotentProvider経由だと思うので、あんまりやることはないと思いますが、試してみました。
CursorにDataSetObserverがあり、対象のデータを更新したら、いい感じに通知があるのかなと思ったのですが、それほどいい感じのようには思えませんでした。
処理の流れは次のようになります。
cursor取得 -> データ更新 -> 明示的にrequeryを呼ぶ -> DataSetObserver経由でonChangedメソッドが呼び出される。
下記コードではやってませんが、Activityのライフサイクルを考慮した場合、cursorを保持し続けるのはどうなんでしょうか?
public class MainActivity extends ActionBarActivity { private TextView textView; private Button btnSelect; private Button btnInsert; private SQLiteDatabase db; // カーソルを保持しておくため private SQLiteCursor cursor; @TargetApi(Build.VERSION_CODES.JELLY_BEAN) @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); btnSelect = (Button)findViewById(R.id.btnSelect); btnInsert = (Button)findViewById(R.id.btnInsert); textView = (TextView)findViewById(R.id.text); MyDBHelper helper = new MyDBHelper(this.getApplicationContext(), "mydb", null, 1); db = helper.getWritableDatabase(); cursor = (SQLiteCursor)db.rawQuery("select id, name, tel, address from people", null, null); cursor.registerDataSetObserver(new DataSetObserver() { @Override public void onChanged() { // このメソッドのパラメータはなし super.onChanged(); updateTextView(); } }); // テーブルの内容表示 btnSelect.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { updateTextView(); } }); // テーブルにデータを登録する btnInsert.setOnClickListener(new View.OnClickListener() { @TargetApi(Build.VERSION_CODES.JELLY_BEAN) @Override public void onClick(View view) { // カーソルを保持するなら件数が数えられるので、idを取り直さなくても良いかも(idがずれない前提であれば) // cursor.getCount() // Cursor c1 = db.rawQuery("select max(id) from people", null, null); // c1.moveToFirst(); // int max = c1.getInt(0); db.beginTransaction(); String name = getTextVal(R.id.editName); String tel = getTextVal(R.id.editTel); String address = getTextVal(R.id.editAddress); db.execSQL("insert into people (id, name, tel, address) values (?, ?, ?, ?)", new Object[]{cursor.getCount() + 1, name, tel, address}); // 更新のケースも対応する場合は、replaceを使った方が楽なはず。 // ContentValues cv = new ContentValues(); // cv.put("id", cursor.getCount() + 1); // cv.put("name", name); // cv.put("tel", tel); // cv.put("address", address); // db.replace("people", null, cv); db.setTransactionSuccessful(); db.endTransaction(); // これの使いどころとしてどんなもんだろうか? cursor.requery(); } }); } private String getTextVal(int resId) { return ((EditText)findViewById(resId)).getText().toString(); } private void updateTextView() { textView.setText(""); cursor.moveToFirst(); do { int id = cursor.getInt(0); String name = cursor.getString(1); String tel = cursor.getString(2); String address = cursor.getString(3); textView.append(id + "," + name + ", " + tel + "," + address + System.getProperty("line.separator")); // 便利なメソッドがあった // 下記のような感じでログがだせる // このメソッドを読んでもカーソル位置は変わらない。 // 05-04 20:54:58.785 9033-9033/com.example.test02 D/test02﹕ 0 { // id=1 // name=satoshi // tel=090-0000-0001 // address=tokyo // } Log.d("test01", DatabaseUtils.dumpCurrentRowToString(cursor)); } while (cursor.moveToNext()); } @Override protected void onDestroy() { if (cursor != null) { cursor.close(); } if (db != null) { db.close(); } super.onDestroy(); } ... }