在安卓上呈现动态表单的方法?

4
我希望在Android开发的广泛领域中,有人曾经遇到过这个问题/用例,并且对实现有一个相对简单的方法。
我有一个客户端Android应用程序,需要呈现一个字段列表,然后最终用户填写。每个字段都是某种已知类型,例如“文本”或“单选”,“多选”等。当用户点击表单时,将向后端发出API调用,该调用返回该表单的模式(即:每个字段的UUID、标题、描述、提示文本等)和该表单的数据,其中一些字段很可能已经从先前的时间填写好了。以下是API调用返回的数据示例:
{
  "submittedBy": 8,
  "updatedBy": 8,
  "createdBy": 8,
  "submittedDateMillis": 1489680600000,
  "updatedDateMillis": 1489680600000,
  "createdDateMillis": 1489680600000,
  "name": "My Form",
  "formTemplateId": 3,
  "id": 0,
  "schema": {
    "6051c1e3-b4bf-4e6a-afe3-de2497dbff11": {
      "units": "ft.",
      "hintText": "Length of measurement",
      "required": false,
      "description": "Take the length of the measured item to 4 decimal places.",
      "title": "Measurement",
      "type": "number"
    },
    "fdf6ff0b-e60d-4591-a3e7-5467cd7bc67e": {
      "enum": [
        "Foo",
        "Bar",
        "Baz",
        "Bat"
      ],
      "required": true,
      "hintText": "",
      "description": "This is a description for a multiple choice question",
      "title": "Multiple Choice (radio) title",
      "type": "radio"
    },
    "203ef6d8-03fe-48e8-9a45-b18d12721d44": {
      "enum": [
        "Option 1",
        "Option 2",
        "Option 3",
        "Option 4"
      ],
      "required": true,
      "hintText": "",
      "description": "This is the description for a multiselect question",
      "title": "This is the title for a multiselect question",
      "type": "multiselect"
    },
    "751e9b8f-a59d-4e81-b3da-17ae44daa44e": {
      "enum": [
        "A dropdown answer",
        "This is another option for a dropdown question it's limit is 130 characters"
      ],
      "required": true,
      "hintText": "",
      "description": "This is the description for a dropdown question",
      "title": "This is the title for a dropdown question",
      "type": "select"
    },
    "33e13828-9171-4680-b68b-9838d4d42af8": {
      "required": true,
      "hintText": "This is the hint text for a text question limit 130 characters",
      "description": "This is the description for a text question limit 5000 characters",
      "title": "This is the title for a text question limit 130 characters",
      "type": "text"
    }
  },
  "fields": {
    "6051c1e3-b4bf-4e6a-afe3-de2497dbff11": "5555.5555",
    "fdf6ff0b-e60d-4591-a3e7-5467cd7bc67e": "Bar",
    "751e9b8f-a59d-4e81-b3da-17ae44daa44e": "A dropdown answer",
    "203ef6d8-03fe-48e8-9a45-b18d12721d44": [
      "Option 1",
      "Option 2",
      "Option 4"
    ],
    "33e13828-9171-4680-b68b-9838d4d42af8": "My answer for your text question."
  }
}

API调用,例如/api/v1/forms/0,返回上述数据。其中有一个描述字段类型的schema,和一个给我填充答案的fields(其中可能会有一些缺失)。它们都有UUID与之对应,因此我知道要将哪个字段数据放入哪个表单字段中。
现在我必须渲染这个表单,并允许用户点击“提交”并将新数据POST/PUT回API。
处理这个问题的方法是什么?我认为自己在Android方面还是个初学者,目前想到的解决方法可能不是最好的(而且可能无法扩展到超过50个问题,在这种情况下,“渲染”和“提交”部分将变得很慢):
  1. 进行API调用,获取数据(参考以上示例)。
  2. 对于每种schema类型,.inflate()一个XML布局,该布局为相应的.typenumbertextradio等),并构造一个Java类型(我称之为FormElement),该类型表示该schema JSON类型。在.inflate()之后,.setTag(formElement)并“附加”该Java FormElement
  3. 获取我们刚才膨胀的布局中的小部件,如果我们有相应的data,则从JSON的fields映射中将数据设置为任何内容。如果没有,则将其留空。
  4. 当用户点击“提交”时,获取父表单视图,然后获取其子项。循环遍历每个子项并通过.getTag()提取其FormElement。获取FormElement#getType以查找View的类型,然后向后工作,并知道我们正在迭代的View,进行转换,获取其内部数据值,重新构建生成的JSON数据,并将其PUT到API。
我可能会为表示数据输入点(文本、单选等)的每个Widget分配一个唯一的ID,基于schema中的UUID(UUID是v1,因此一种方法是获取时间戳并希望最好,因为我们会从128位变为32位)。然后在需要在用户点击提交后拉出数据时使用此ID。
Android的Data Binding Library看起来具有一些有前途的功能,但我不认为Android的数据绑定可以处理此UI的“动态”特性,其中包括具有不同数据类型的不同小部件(其中一些是下拉菜单)。
  1. 这里数据绑定是更好的方法吗?
  2. 数据绑定能否处理UI渲染和从UI获取数据以最终组合我的API PUT请求发送回服务器的两个问题?

迄今为止我查看的一些资源,可以解决这个总体问题:

提前感谢大家!

1个回答

5
您��该在内存中创建这些字段的表示形式(例如Field集合)。然后您可以使用RecyclerView来高效地布局它们。在RecyclerView中,您可以拥有视图类型���每种字段类型一个),用于处理特定字段。在RecyclerView内部,为了绑定视图,您可以使用数据绑定。在github上有一个演示,展示了如何有效地使用Data Binding与RecyclerView。
最后但并非最不重要的是,请确保您的网络操作完全解耦自UI。UI只读取集合,因此每次进行网络请求时,它都会更新集合,并通知更改,RecyclerView将自行更新。(您可能希望在集合上进行乐观更新,因为网络请求可能需要时间,但这是一个需要详细探讨的大主题)。

谢谢Yigit,我按照这个方法做了,目前看起来还不错。唯一的问题是没有办法“迭代”布局(XML)以构建单个小部件(例如作为RadioGroup的一部分的RadioButton)。我的解决方案是子类化RadioGroup并尝试对该子类小部件进行数据绑定。 - Jack
请告诉我你是如何处理的,我也在做同样的应用程序。 - Barungi Stephen

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接