我希望在Android开发的广泛领域中,有人曾经遇到过这个问题/用例,并且对实现有一个相对简单的方法。
我有一个客户端Android应用程序,需要呈现一个字段列表,然后最终用户填写。每个字段都是某种已知类型,例如“文本”或“单选”,“多选”等。当用户点击表单时,将向后端发出API调用,该调用返回该表单的模式(即:每个字段的UUID、标题、描述、提示文本等)和该表单的数据,其中一些字段很可能已经从先前的时间填写好了。以下是API调用返回的数据示例:
API调用,例如
现在我必须渲染这个表单,并允许用户点击“提交”并将新数据
处理这个问题的方法是什么?我认为自己在Android方面还是个初学者,目前想到的解决方法可能不是最好的(而且可能无法扩展到超过50个问题,在这种情况下,“渲染”和“提交”部分将变得很慢):
Android的Data Binding Library看起来具有一些有前途的功能,但我不认为Android的数据绑定可以处理此UI的“动态”特性,其中包括具有不同数据类型的不同小部件(其中一些是下拉菜单)。
我有一个客户端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个问题,在这种情况下,“渲染”和“提交”部分将变得很慢):
- 进行API调用,获取数据(参考以上示例)。
- 对于每种
schema
类型,.inflate()
一个XML布局,该布局为相应的.type
(number
、text
、radio
等),并构造一个Java类型(我称之为FormElement
),该类型表示该schema JSON类型。在.inflate()
之后,.setTag(formElement)
并“附加”该JavaFormElement
。 - 获取我们刚才膨胀的布局中的小部件,如果我们有相应的data,则从JSON的
fields
映射中将数据设置为任何内容。如果没有,则将其留空。 - 当用户点击“提交”时,获取父表单视图,然后获取其子项。循环遍历每个子项并通过
.getTag()
提取其FormElement
。获取FormElement#getType
以查找View的类型,然后向后工作,并知道我们正在迭代的View,进行转换,获取其内部数据值,重新构建生成的JSON数据,并将其PUT
到API。
Widget
分配一个唯一的ID,基于schema
中的UUID(UUID是v1,因此一种方法是获取时间戳并希望最好,因为我们会从128位变为32位)。然后在需要在用户点击提交后拉出数据时使用此ID。Android的Data Binding Library看起来具有一些有前途的功能,但我不认为Android的数据绑定可以处理此UI的“动态”特性,其中包括具有不同数据类型的不同小部件(其中一些是下拉菜单)。
- 这里数据绑定是更好的方法吗?
- 数据绑定能否处理UI渲染和从UI获取数据以最终组合我的API PUT请求发送回服务器的两个问题?
迄今为止我查看的一些资源,可以解决这个总体问题:
- http://www.mysamplecode.com/2011/10/android-dynamic-layout-using-xml-add.html 用于基于预定义XML添加/膨胀UI。
- https://realm.io/news/data-binding-android-boyar-mount/ 由@george-mount进行的非常好的技术讲座,涵盖了数据绑定的一些基础知识。
.setTag()
&.getTag()
- View的setTag() getTag()方法的主要目的是什么? 这似乎符合我的用例,其中我需要让视图“知道”有关自己的一些信息(例如它们在JSON响应中来自哪里)。
提前感谢大家!