我想要编写一个ListAdapter来提供来自数据库的数据,如下所示:
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内容。我可以用下面的查询查询数据库中的所有注释:
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;这将给我如下所示的结果(为清楚起见,显示空值):
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()
private void initializeCursors() {
notesCursor.moveToFirst();
countCursor.moveToFirst();
count = countCursor.getInt(0);
}我已经像这样实现了getItem():
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的某些部分?
提前感谢!
发布于 2011-01-21 22:06:18
根据ContentProvider的实现方式,如果您选择扩展CursorAdapter而不是ListAdapter,则可能会自动为您处理此功能。
如果您在您的ContentProvider中调用类似以下内容:
getContext().getContentResolver().notifyChange(uri, myObserver);当您更改某些内容(插入、删除、更新)时(根据'notifyChange()‘函数的文档:http://developer.android.com/reference/android/content/ContentResolver.html),CursorAdapters将默认收到此通知。
最后,我将对您的数据库结构发表一点意见(请不要感到被冒犯,我不是故意粗鲁,我只是想提供帮助)。
注#1许多数据库架构师声明,用单数命名表是“事实上的标准”,因此,如果将两个表分别命名为" NOTE“和"tag”,看起来可能会更专业一些。
注意#2在你的笔记和标签之间似乎有一种多对多的关系(一个笔记可以有多个标签,但一个标签也可以属于多个笔记)。然后,为了避免“标记”表中的重复数据,最好将“注释”和“标记”彼此完全分开,并引入第三个表,例如“关系”,它将描述您的注释和标记之间的关系。然后,您将拥有三个表,如下所示:
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查询(其中所有内容都被选中)将如下所示:
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查询将如下所示:
SELECT tag.* FROM relation
LEFT JOIN tag ON (tag._id = relation.tag_id)
WHERE relation.note_id=12;当然,你可以用当前音符的id替换'12‘。
我希望你能利用我的(很长的:-)答案。
https://stackoverflow.com/questions/4756500
复制相似问题