私は同じ問題に直面していました。実際、多くの人がそうだと思います。URIのメカニズム全体(contentproviderを介したリレーショナルDB、およびその周りに構築されたすべて(さまざまな変更リスナー、ファイルおよびストリーム処理など))は、すべて非常に印象的で便利ですが、非常に単純なデータモデルの場合です。
アプリケーションで、テーブルの階層、オブジェクトリレーショナルセマンティクスなど、より複雑なデータモデルが必要になると、このモデルは機能しなくなります。Android用のORMツールをたくさん見つけましたが、それらは私にはあまりにも「最先端」のように見えます(さらに、私の人生では、それらがデータ変更通知をサポートしているかどうかを理解できませんでした)。
ORMは今日非常に一般的です。Androidの人々が同意し、プラットフォームにORM機能を追加することを本当に望んでいます。
これが私がやったことです。正しい内部カーソルを選択するのに役立つ先頭のインデックスカーソルを備えたカーソルのカーソル。これは一種の一時的な解決策です。コードを続行して、後でこれに戻る必要がありました。お役に立てれば。もちろん、リストビューを使用する場合は、カスタムアダプターを作成して、正しいビューを膨らませ、バインドを行う必要があります。
public class MultiCursor implements Cursor {
private final String TAG = this.getClass().getSimpleName();
ArrayList<Cursor> m_cursors = new ArrayList<Cursor>();
Map<Long, CursorRowPair> m_idToCursorRow = Collections.synchronizedMap(new HashMap<Long, CursorRowPair>());
Set<Long> m_idSet = new HashSet<Long>();
Cursor m_idCursor;
/**
* @precondition: _id column must exist on every type of cursor, and has to have index of 0 (be the first)
* @param idCursor
*/
public MultiCursor(Cursor idCursor) {
m_idCursor = idCursor;// this cursor binds the order (1,2,3) to ids
// go over all the ids in id cursor and add to m_idSet
initIdSet();
// m_cursors.add(idCursor);
// m_position = -1;
}
private void initIdSet() {
m_idSet.clear();
long id;
m_idCursor.moveToPosition(-1);
while (m_idCursor.moveToNext()) {
id = m_idCursor.getLong(m_idCursor.getColumnIndex(ContentDescriptor.ShowViewItem.Cols.ID));
m_idSet.add(id);
}
m_idCursor.moveToFirst();
}
public void addCursor(Cursor cursor) {
// when something changes in the child cursor, notify parent on change, to notify subscribers
// cursor.registerContentObserver(new SelfContentObserver(this)); // calls my onchange, which calls the ui
m_cursors.add(cursor);
updateIdToCursorMap(cursor);
}
private class CursorRowPair {
public final Cursor cursor;
public final int row;
public CursorRowPair(Cursor cursor, int row) {
this.cursor = cursor;
this.row = row;
}
}
private void updateIdToCursorMap(Cursor cursor) {
// get object_type
// for each row in cursor, take id, row number
// add id, <cursor,rowNum> to map
long id;
int row = 0;
cursor.moveToPosition(-1);
while (cursor.moveToNext()) {
id = cursor.getLong(cursor.getColumnIndex(ContentDescriptor.ShowViewItem.Cols.ID));
if (m_idSet.contains(id)) m_idToCursorRow.put(id, new CursorRowPair(cursor, row));
row++;
}
cursor.moveToFirst();
}
private Cursor getInternalCursor() {
if (getPosition() < 0 || getCount()==0) return m_idCursor; // todo throw a proper exception
// get the id of the current row
long id = m_idCursor.getLong(m_idCursor.getColumnIndex(ContentDescriptor.BaseCols.ID));
CursorRowPair cursorRowPair = m_idToCursorRow.get(id);
if (null == cursorRowPair) return null;
Cursor cursor = cursorRowPair.cursor;
int row = cursorRowPair.row;
cursor.moveToPosition(row);
return cursor;
}
// //////////////////////////////////////////////
@Override
public void close() {
Log.d(TAG, "close");
for (Cursor cursor : m_cursors) {
cursor.close();
}
m_idCursor.close();
}
@Override
public void copyStringToBuffer(int columnIndex, CharArrayBuffer buffer) {
Log.d(TAG, "copyStringToBuffer");
getInternalCursor().copyStringToBuffer(columnIndex, buffer);
}
などなどなど。