2

我有一个ContentProvider通过将数据加载CursorLoader到列表视图(带有自定义CursorAdapter)的工作实现。这是一个事件列表。每个项目都有一个标题、位置等,还有一组应显示在LinearLayout每个列表行内的报价。

问题是Cursor一行只能包含平面数据,而不是一组其他项目。

我唯一的想法是像这样对数据库进行连接查询:

SELECT * FROM events, offers WHERE events.id=offers.event_id;

但是,我将拥有与报价一样多的行(并且列表应该显示事件,所以这不好)并且列表会人满为患。也许有可能告诉CursorAdapter只填充具有唯一性events.id但以某种方式检索优惠数据的列表行?

最好的解决方案是在 events中放置一个Cursor或自定义包含 offer 。但是,这是不可能的。ObjectCursor

4

3 回答 3

3

我面临着同样的问题。事实上,我想很多人都是。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);
}

等等等等等等

于 2012-09-22T06:56:04.720 回答
0

在您的适配器中,查询所有记录的提供游标并将其设为类变量。然后在您getView使用事件 id 来遍历提供光标并在找到合适的匹配项时将必要的文本视图添加到您的行布局中。它并不优雅,但它应该可以工作。

于 2012-06-17T21:54:02.170 回答
0

不幸的是,一个CursorLoader只能加载一个Cursor。所以解决方案是编写一个AsyncTaskLoader返回两个的自定义Cursors

于 2012-07-11T12:37:17.223 回答