我面临着同样的问题。事实上,我想很多人都是。URI 的整个机制——通过 contentprovider 到关系数据库,以及围绕它构建的所有内容(如各种更改侦听器、文件和流处理)——这一切都非常令人印象深刻和有用,但对于非常简单的数据模型而言。
一旦您的应用程序需要更精细的数据模型,例如 - 表的层次结构、对象关系语义 - 这个模型就会中断。我找到了一堆适用于 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);
}
等等等等等等