ListView的优化建议,包含来自多个"表"的数据

Jur*_*uri 5 optimization android listview

我刚遇到以下情况.我有一个Android应用程序,我猜可能会在多个应用程序中发生.它是关于标记/标记/分类,根据需要调用它.我在SQLite DB中基本上有以下关系

 --------                 --------------              ---------
|  Tags  |               |  DeviceTags  |            | Devices |
|--------|               |--------------|            |---------|
| ID     | 1 ------ *    | ID           | * ------ 1 | ID      |
| NAME   |               | TAGS_ID      |            | NAME    |
 --------                | DEVICE_ID    |            | ...     |
                          --------------              ---------
Run Code Online (Sandbox Code Playgroud)

一切都暴露在我写过的ContentProvider上.到目前为止一切都很好.

在UI部分,我有一个ListActivity显示所有存储的设备(来自Devices表),并且为了进一步自定义UI,我创建了自定义行项目,根据设备类型等显示前面的小图像.

我现在想要实现的是还在每个设备的列表上显示相关标签.现在我的问题来了.对于简单的设备列表,我创建了一个自定义的ResourceCursorAdapter,我在bindView方法中设置相应的信息

@Override
public void bindView(final View view, final Context context, final Cursor cursor) {
  final int objectId = cursor.getInt(cursor.getColumnIndex(Devices._ID));

  TextView deviceName = (TextView) view.findViewById(R.id.deviceName);
  deviceName.setText(...); //set it from the cursor
  ...
  TextView associatedTagsView = (TextView)...;
  associatedTagsView.setText(...); //<<<???? This would need a call to a different table
  ...
}
Run Code Online (Sandbox Code Playgroud)

如您所见,为了能够知道我的设备与哪种标签相关联,我需要查询DeviceTags.所以我做了:

@Override
public void bindView(final View view, final Context context, final Cursor cursor) {
   ...
   TextView associatedTagsView = (TextView)view.findViewById(R.id.deviceTags);
   String tagsString = retrieveTagsString(view.getContext().getContentResolver(), objectId);
   ...
}

private String retrieveTagsString(ContentResolver contentResolver, int objectId) {
    Cursor tagForDeviceCursor =  contentResolver.query(DroidSenseProviderMetaData.TABLE_JOINS.TAG_DEVICETAG,...);
    if(tagForDeviceCursor != null && tagForDeviceCursor.moveToFirst()){
        StringBuffer result = new StringBuffer();

        boolean isFirst = true;
        do{
            if(!isFirst)
                result.append(", ");
            else
                isFirst = false;

            result.append(retrieve name from cursor column...);
        }while(tagForDeviceCursor.moveToNext());

        return result.toString();
    }       
    return null;
}
Run Code Online (Sandbox Code Playgroud)

我测试了它,它实际上工作得很好,但老实说我做得不好.不知怎的,对我来说似乎很奇怪......

有没有更好的解决方案如何解决这个?

//编辑:

在CommonsWare的反馈之后,这里有一点澄清.我对在CursorAdapter中对DB进行第二次查询很奇怪,基本上这会导致每行一次查询,我担心这会严重影响我的性能(我还是要在真实的设备上测试它有大量的数据,看看这有多大影响).

因此,我的问题在于是否有一些关于如何避免这种情况的策略,因为我的数据模型或者我是否必须基本上"生活"了:)

Jur*_*uri 0

我用大约 100 个条目测试了我的解决方案(在我的问题中提出)。它仍然可用,但滚动并不像人们想象的那么顺利。正如 CommonsWare 已经指出的那样,最好的方法是调整数据模型,或者至少正确聚合它,最终光标包含在 UI 上显示所需的所有数据

我不想完全改变底层数据模型。我所做的是以某种方式聚合数据,ContentProvider 返回的游标包含设备的数据,包括表示关联标签名称的已准备好的字符串:

| ID | NAME             | ... | LABELSSTRING   |
------------------------------------------------
| 1  | "My Device name" | ... | "Work, Friend" |
| 1  | "Some other"     | ... |                |
| 1  | "Yet another"    | ... | "Work"         |
Run Code Online (Sandbox Code Playgroud)

这几乎解决了问题,因为不需要在 CursorAdapter 的 bindView(..) 中为每个设备重新查询,顺便说一句。是相当糟糕的。通过使用 SQLite 的group_concat(X, Y) 函数可以实现此解决方案。