ContentProvider - 返回多个游标或自定义对象

时间:2012-06-17 21:41:28

标签: android sqlite

我通过ContentProviderCursorLoader加载数据工作实现到列表视图中(使用自定义CursorAdapter)。这是一系列事件。每个项目都有标题,地点等,还有一组优惠,应在每个列表行的LinearLayout内显示。

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

我唯一的想法是在数据库上进行加入查询,如下所示:

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

但是那时我会有多少行(和列表应该显示事件,所以它不好),列表会过多。也许有可能告诉CursorAdapter仅使用唯一events.id填充列表行,但也会以某种方式检索商品数据?

最佳解决方案是在事件Cursor中放置包含商品的Object或自定义Cursor。但是afaik它是不可能的。

3 个答案:

答案 0 :(得分:3)

我遇到了同样的问题。事实上,我认为很多人都是。 URI的整个机制 - 通过contentprovider到关系数据库,以及围绕它构建的所有内容(比如各种更改侦听器,文件和流处理) - 这对于非常简单的数据模型来说非常令人印象深刻和有用。

一旦您的应用程序需要更复杂的数据模型,例如 - 表的层次结构,对象关系语义 - 此模型就会中断。 我找到了一堆用于Android的ORM工具,但它们对我来说似乎太“尖锐”了(另外,对于我的生活,我无法弄清楚他们是否有数据更改通知支持)。

ORM今天非常普遍,我真的希望Android用户同意并在平台上添加ORM功能。

这就是我最终做的事情: 游标光标,带有一个前导索引光标,有助于选择正确的内部曲线。 这是一种临时解决方案,我只需继续使用我的代码并稍后再回过头来。希望这可以帮助。 当然,如果您使用listview,您可能还需要创建一个自定义适配器来扩展正确的视图,并进行绑定。

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);
}
等等等。

答案 1 :(得分:0)

在您的适配器中查询所有记录的商品光标并使其成为类变量。然后在getView中使用事件ID迭代商品光标,并在找到合适匹配时将必要的文本视图添加到行布局中。它不优雅,但应该有效。

答案 2 :(得分:0)

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