2

ContentProviderリストビューへのデータのロードの実用的な実装がありますCursorLoader( custom を使用CursorAdapter)。イベント一覧です。すべてのアイテムにはタイトル、場所などがありますが、すべてのリスト行の内側に表示されるオファーのセットもあります。LinearLayout

問題は、Cursor行にはフラット データのみを含めることができ、他の項目のセットを含めることができないことです。

私の唯一のアイデアは、次のようにデータベースに結合されたクエリを作成することです:

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

しかし、オファーと同じ数の行があり (リストにはイベントを表示する必要があるため、これは適切ではありません)、リストが過密になります。おそらくCursorAdapter、一意のリスト行にのみ入力するように指示する可能性がありevents.idますが、何らかの方法でオファーデータも取得できますか?

最善の解決策は、CursorまたはカスタムObjectを含むオファーを events 内に配置することCursorです。しかし、それは不可能です。

4

3 に答える 3

3

私は同じ問題に直面していました。実際、多くの人がそうだと思います。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);
}

などなどなど。

于 2012-09-22T06:56:04.720 に答える
0

アダプタクエリでは、すべてのレコードのオファーカーソルをクラス変数にします。次にgetView、イベント ID を使用してオファー カーソルを反復処理し、適切な一致が見つかったら必要なテキストビューを行レイアウトに追加します。エレガントではありませんが、うまくいくはずです。

于 2012-06-17T21:54:02.170 に答える