使用 Android 和 XML 构建动态用户界面(7)
 
- UID
- 1066743
|

使用 Android 和 XML 构建动态用户界面(7)
当用户输入一个表单编号并点击 Run Form 按钮时,一系列事件将被触发。我们逐行查看一下 onClick() 方法。还记得吗,onClick() 方法位于 XmlGui 类中(见 清单 4)。
您得到了一个名为 formNumber 的 EditText 字段的引用。只要保存 main.xml,Android 构建工具将自动生成 R.id.formNumber 清单:
1
| EditText formNumber = (EditText) findViewById(R.id.formNumber);
|
接下来,您将这一行放置到日志中。您可以在 Eclipse 中的 Dalvik Debug Monitor Service (DDMS) 透视图中查看该日志的输出,该透视图由 Android Developer Tools 插件提供:
1
| Log.i(tag,"Attempting to process Form # [" + formNumber.getText().toString() + "]");
|
Form Engine 的实际实现在 RunForm 类中提供,该类扩展 Activity 类。要启动这个 Activity,创建一个 Intent,显式制定 RunForm class:
1
| Intent newFormInfo = new Intent(XmlGui.this,RunForm.class);
|
您不仅想启动 RunForm Activity,还想指定显示哪个表单。为此,通过 putExtra 方法将表单编号添加到 Intent:
1
| newFormInfo.putExtra("formNumber", formNumber.getText().toString());
|
这个值通过 RunForm 类提取,我们将稍后展示。
您已经设置了 Intent,现在可以通过对 startActivity 的一个调用来启动 Activity:
1
| startActivity(newFormInfo);
|
通过您的应用程序,用户输入表单编号并单击 Run Form 按钮。这将触发上面描述的事件,导致 RunForm 类处理请求。输入一个表单编号仅仅是本教程的一个测试工具,还有其他一些方式可以导致这个触发事件发生。更实用的示例包括来自一个 web 页面的定制链接,通过 Short Message Service (SMS) 推送的短消息,根据相邻性(proximity)的基于位置的触发器,或者甚至是一个经过扫描的 QR(Quick Response)代码。
运行表单RunForm 类是这个应用程序的编排器,通过一个要处理的表单编号启动。现在检查 中的 onCreate() 方法。
清单 6. onCreate() 方法1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
| public class RunForm extends Activity {
/** Called when the activity is first created. */
String tag = RunForm.class.getName();
XmlGuiForm theForm;
ProgressDialog progressDialog;
Handler progressHandler;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
String formNumber = "";
Intent startingIntent = getIntent();
if(startingIntent == null) {
Log.e(tag,"No Intent? We're not supposed to be here...");
finish();
return;
}
formNumber = startingIntent.getStringExtra("formNumber");
Log.i(tag,"Running Form [" + formNumber + "]");
if (GetFormData(formNumber)) {
DisplayForm();
}
else
{
Log.e(tag,"Couldn't parse the Form.");
AlertDialog.Builder bd = new AlertDialog.Builder(this);
AlertDialog ad = bd.create();
ad.setTitle("Error");
ad.setMessage("Could not parse the Form data");
ad.show();
}
}
// other methods omitted and shown later
}
|
如 中的代码所示,首先从触发 Activity 的 Intent 提取 formNumber。由于没有要处理的表单编号,这个 Activity 没有可以执行的内容。
提取这个值后,下一个要求是连接到服务器以下载表单规范。(注意,这种方法的一个增强可能是在获取这个数据之前在本地缓存逐行提取这个表单的元数据。) 展示了 GetFormData() 方法。
清单 7. GetFormData() 方法1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
| private boolean GetFormData(String formNumber) {
try {
Log.i(tag,"ProcessForm");
URL url = new URL("http://www.example.com/xmlgui" + formNumber + ".xml");
Log.i(tag,url.toString());
InputStream is = url.openConnection().getInputStream();
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder db = factory.newDocumentBuilder();
Document dom = db.parse(is);
Element root = dom.getDocumentElement();
NodeList forms = root.getElementsByTagName("form");
if (forms.getLength() < 1) {
// nothing here??
Log.e(tag,"No form, let's bail");
return false;
}
Node form = forms.item(0);
theForm = new XmlGuiForm();
// process form level
NamedNodeMap map = form.getAttributes();
theForm.setFormNumber(map.getNamedItem("id").getNodeValue());
theForm.setFormName(map.getNamedItem("name").getNodeValue());
if (map.getNamedItem("submitTo") != null)
theForm.setSubmitTo(map.getNamedItem("submitTo").getNodeValue());
else
theForm.setSubmitTo("loopback");
// now process the fields
NodeList fields = root.getElementsByTagName("field");
for (int i=0;i<fields.getLength();i++) {
Node fieldNode = fields.item(i);
NamedNodeMap attr = fieldNode.getAttributes();
XmlGuiFormField tempField = new XmlGuiFormField();
tempField.setName(attr.getNamedItem("name").getNodeValue());
tempField.setLabel(attr.getNamedItem("label").getNodeValue());
tempField.setType(attr.getNamedItem("type").getNodeValue());
if (attr.getNamedItem("required").getNodeValue().equals("Y"))
tempField.setRequired(true);
else
tempField.setRequired(false);
tempField.setOptions(attr.getNamedItem("options").getNodeValue());
theForm.getFields().add(tempField);
}
Log.i(tag,theForm.toString());
return true;
} catch (Exception e) {
Log.e(tag,"Error occurred in ProcessForm:" + e.getMessage());
e.printStackTrace();
return false;
}
}
|
这段代码负责从一个元数据存储库提取数据,在本例中是从一个 web 服务器下载一个 XML 文件:
1
| URL url = new URL("http://10.211.55.2/~fableson/xmlgui" + formNumber + ".xml");
|
|
|
|
|
|
|