游标适配器中的多个表(或MergeAdapter

时间:2014-07-20 03:02:32

标签: android android-cursoradapter android-cursor commonsware-cwac

我正在建造一个使用两张桌子的健身追踪器。一个是Workout_Container,可以有多个动作。接下来是Movements表,其中包含实际移动(名称,重量,百分比等)。每个表都作为唯一键字段(_id),但Movement有一个Workout_Container的_id字段,因为这是一个关系数据库。因此,对于Workout Container的一个记录,它可以在Movement表中有多个条目。

架构是:

Main(_id INTEGER PRIMARY KEY AUTOINCREMENT, Workout_Date TEXT)      

Workout_Container (_id INTEGER PRIMARY KEY AUTOINCREMENT, Date_ID INTEGER, AMRAP INTEGER, Rounds INTEGER, Finish_Time TEXT, Rounds_Finished INTEGER, IsWeight_Workout TEXT, Workout_Name TEXT, Comments TEXT).  

Movement_Template (_id INTEGER PRIMARY KEY AUTOINCREMENT, Workout_Container_ID INTEGER, Sets INTEGER, Reps INTEGER, Movement TEXT, Time_of_Movement TEXT, Length INTEGER, Weight INTEGER, Percentage INTEGER, Comments TEXT). 

主要 Workout_Container 的父级,他是锻炼模板的父级。我只关心最后两张表作为第一张(虽然看似多余)在其他地方用于显示日历,我想要一张较小的表格,以便我查询某一天是否存在锻炼。

在视觉上,这看起来类似于List适配器,但是以分层方式,因为Workout Container将是其下面列出的任何Movements的父级。 Workout容器在视觉上与Movements ....不同......看起来像这样......这意味着getView需要知道要加载的特定.xml格式。

Workout Container (_id = 45)
===============
*Movement 1  (movement with Container_id = 45)*

*Movement 2  (movement with Container_id = 45)*

*Movement 3  (movement with Container_id = 45)*

Workout Container (_id = 46)
==============
*Movement 1   (movement with Container_id = 46)*

*Movement 2   (movement with Container_id = 46)*

ViewAdapterCursorAdapter)给出的每一行都是MergeAdapter。用户可以选择这些行并对其进行编辑或删除。是的,我将有一个添加行的功能,但尚未到达那里。现在,我在Cursor查询中合并两个表,抓取当天Workout_Container中的所有行,以及Movement中与通过JOIN在Workout_Container中抓取的行对应的所有行。但这让我合并了两个表并且在一个CursorAdapter中,我无法分辨我是否应该显示一个Workout_Container .xml或一个Movement .xml,因为我不知道过去的那一行我在getView中显示行时显示。上面的示例将在查询中返回5行,其中Workout Container _id = 45在Cursor中被复制3次,而Workout_Container _id = 46信息在Cursor中重复2次。

我的问题是:我将如何展示这个?

选项1:我应该将两个表合并到一个光标视图中吗?如果是这样,那么我如何知道要输出哪个视图,因为可以为多个记录复制锻炼容器信息,我不能回头查看该行以确定是否必须显示新的锻炼容器? CursorAdapter每行需要一个唯一的ID号,并且我可能不会拥有它,因为这两个表的每个_id都是独立的。

选项2:使用合并适配器,抓取当天锻炼容器的单行,并将每行放在自己的光标中。然后获取与给定Workout Container _id相对应的每个Movement的一行,并将其移动到其自己的Cursor中。将每个Cursor作为自己的MergeAdapter加入CursorAdapter。我基本上会有一个CursorAdapters数组,只有一行。基本上是通过一个嵌套的循环,它会在它穿过时抓住游标。这会是一次重大的性能打击,因为我可能会在CursorAdapters内打开一些MergeAdapter吗?

选项3:创建一个复制每个表的类,并将一行倒入一个类数组中,然后生成一组类,然后将这些类发送到MergeAdapter。这似乎是最困难的,因为我必须覆盖CursorAdapter已经处理过的更多项目。

现在,我在一个片段中的AsyncTask内的AsyncTask内一次性抓取Workout_Container和Movements中所有相关行,隐藏其唯一的工作是Activity项目。并将其交回AsyncTask。我是否需要将每行{{1}}移到适配器上,一次创建一个视图,而不是整行光标并通过它?

我希望这一切都有意义,因为我一直在绞尽脑汁,唯一似乎很容易的事情就是选项2 ....我搜索并没有发现任何有助于这种特定情况的东西。

1 个答案:

答案 0 :(得分:2)

  

我将如何显示此内容?

我会使用选项#2,#3或#4。

选项#4:使用ExpandableListView,它似乎具有您想要的UI,增加了用户扩展和折叠的能力,是否显示特定锻炼的动作。

  

由于我可能在MergeAdapter中打开了许多CursorAdapter,这会对性能造成重大影响吗?

不是从显示的角度来看。加载数据会有点昂贵,因为你要进行N + 1个查询:一个用于锻炼,一个用于锻炼的每组动作。

您可以通过创建覆盖CursorWindowAdaptergetCount()以及其他内容的moveToPosition()来改善这一点,以使其“适应”Cursor的子集(开始位置和行数#)。然后你只需要两个查询:一个用于锻炼,一个用于所有动作,后者通过锻炼排序。然后,您将浏览一下Cursor移动,为每个锻炼的一组动作构建CursorWindowAdapter个实例。我不知道创建一个可靠的CursorWindowAdapter是多么容易或多么困难。而且,如果您的数据集较小,您可能会在没有它的情况下逃脱。

  

这似乎是最困难的,因为我必须覆盖CursorAdapter已经处理的更多项目。

更大的问题是:您打算如何处理超越在此列表中显示的数据?如果您的整体预期用途更适合应用于POJO而不是Cursor条目,那么将您的数据集转换为合适的POJO树可能是值得的。不要孤立地考虑显示列表问题。

  

我是否需要将AsyncTask的每一行都移交给适配器,一次创建一个视图,而不是整行的Cursor并通过它?

这是MergeAdapter方案的另一种方式:您必须等到所有查询完成,然后在{{{{}}中构建MergeAdapter 1}}。 onPostExecute()的一大限制是,一旦将其附加到MergeAdapter,就无法为其添加更多适配器/视图。