首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >ListAdapter设计建议

ListAdapter设计建议
EN

Stack Overflow用户
提问于 2011-01-21 15:43:11
回答 1查看 436关注 0票数 0

我想要编写一个ListAdapter来提供来自数据库的数据,如下所示:

代码语言:javascript
复制
CREATE TABLE notes (_id integer primary key, 
                    content text);
CREATE TABLE tags (_id integer primary key,
                   name text,
                   pos integer
                   noteid integer,
                   foreign key(noteid) references notes(_id));

我使用这个数据库来存储笔记及其相关的标记。ListAdapter的一个要求是,如果底层数据发生更改,它必须能够更新ListView内容。我可以用下面的查询查询数据库中的所有注释:

代码语言:javascript
复制
select notes._id as id, notes.content, tags.pos, tags.name 
  from notes left join tags on id = tags.noteid
  order by id, tags.pos;

这将给我如下所示的结果(为清楚起见,显示空值):

代码语言:javascript
复制
0|foo bar baz|0|x
1|hello world|null|null
2|one more nn|0|yy
2|one more nn|1|y

如您所见,具有多个标记的注释将位于结果中的多个行上。这意味着我不能通过查看光标大小来确定音符的数量,我需要遍历整个光标才能获得计数。我不想那样做。

到目前为止,我想出的解决方案是使用两个游标:一个使用上面提到的查询,另一个使用包含notes表中的行数的查询(select count(*) from notes)。在构造函数中,我调用了intializeCursors()

代码语言:javascript
复制
private void initializeCursors() {
    notesCursor.moveToFirst();
    countCursor.moveToFirst();
    count = countCursor.getInt(0);
}

我已经像这样实现了getItem():

代码语言:javascript
复制
public Note getItem(int position) {
    // notes is a List of notes that we have already read.
    if (position < notes.size()) { 
        return notes.get(position);
    }

    int cursorPosition = notes.size();
    while (cursorPosition <= position) {
        // Creates a note by reading the correct number of rows.
        Note note = NotesDb.noteFrom(notesCursor); 
        notes.add(note);
        ++cursorPosition;
    }
    return notes.get(position);
}

适配器假定游标由在游标上调用startManagingCursor()的某个活动管理。

到目前为止,我想一切都还不错。现在的问题是如何处理被重新查询的游标。因为我有两个游标,所以我需要为这两个游标注册侦听器,当我收到这两个游标的onChange()时,我可以initializeCursors()并通知注册到我的ListAdapter中的任何侦听器its数据的变化。

这是我到目前为止最好的了。我想和这个小组一起检查这种方法的合理性。:-)这是不是太复杂了?也许我错过了为我很好地解决这个问题的API的某些部分?

提前感谢!

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2011-01-21 22:06:18

根据ContentProvider的实现方式,如果您选择扩展CursorAdapter而不是ListAdapter,则可能会自动为您处理此功能。

如果您在您的ContentProvider中调用类似以下内容:

代码语言:javascript
复制
getContext().getContentResolver().notifyChange(uri, myObserver);

当您更改某些内容(插入、删除、更新)时(根据'notifyChange()‘函数的文档:http://developer.android.com/reference/android/content/ContentResolver.html),CursorAdapters将默认收到此通知。

最后,我将对您的数据库结构发表一点意见(请不要感到被冒犯,我不是故意粗鲁,我只是想提供帮助)。

注#1许多数据库架构师声明,用单数命名表是“事实上的标准”,因此,如果将两个表分别命名为" NOTE“和"tag”,看起来可能会更专业一些。

注意#2在你的笔记和标签之间似乎有一种多对多的关系(一个笔记可以有多个标签,但一个标签也可以属于多个笔记)。然后,为了避免“标记”表中的重复数据,最好将“注释”和“标记”彼此完全分开,并引入第三个表,例如“关系”,它将描述您的注释和标记之间的关系。然后,您将拥有三个表,如下所示:

代码语言:javascript
复制
CREATE TABLE note (_id INTEGER PRIMARY KEY, 
                   content TEXT);

CREATE TABLE tag (_id INTEGER PRIMARY KEY,
                  name TEXT,
                  pos INTEGER);

CREATE TABLE relation (_id INTEGER PRIMARY KEY,
                       note_id INTEGER,
                       tag_id INTEGER);

这种架构更改会增加数据库的复杂性,但也会使其容错能力更强(尤其是对更改的容错能力)、从某些角度看速度更快(数据库在筛选查询时不需要测试所有的重复项),并且占用的空间更少。随着数据库的增长,这些“新特性”变得更加有趣。

然后,一个典型的SELECT查询(其中所有内容都被选中)将如下所示:

代码语言:javascript
复制
SELECT note._id AS noteid, note.text, tag.name, tag.pos FROM note
LEFT JOIN relation ON (relation.note_id = note._id)
LEFT JOIN tag ON (tag._id = relation.tag_id);

注意#3:这就引出了我的最后一点。我真的不知道你的应用程序是什么样子的,所以我在这里很可能是错的,但尽管如此:你真的需要同时从两个表(目前是"notes“和”tag“)获得所有信息吗?是否可以仅获取所有“备注”,并将其显示在某种列表或其他GUI星座中,并仅在编辑或查看单个备注时才获取相应的标记?这样你就可以去掉多余的“计数”光标了。

用于获取属于给定注释的所有标记的SELECT查询将如下所示:

代码语言:javascript
复制
SELECT tag.* FROM relation
LEFT JOIN tag ON (tag._id = relation.tag_id)
WHERE relation.note_id=12;

当然,你可以用当前音符的id替换'12‘。

我希望你能利用我的(很长的:-)答案。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/4756500

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档