android 读取自定义xml文件路径,仿京东商城系列18------xml文件读取(地址选择器)...

前言

我们接着上一更的内容,上一更我们集成并使用了支付SDK完成了模拟支付。但我们的订单编辑页面地址与收货人信息一栏还是空白,今天我们要做的就是填充这个空白。效果图如下:

fd16011c704d

地址选择器.gif

内容

补充新知识

xml文件读取

解析方式

1、DOM解析器

DOM(Document Object Model) 是一种用于XML文档的对象模型,可用于直接访问XML文档的各个部分。它是一次性全部将内容加载在内存中,生成一个树状结构,它没有涉及回调和复杂的状态管理。 缺点是加载大文档时效率低下,所以一般在解析大文档时不建议使用DOM解析。

分析该结构通常需要加载整个文档和构造树形结构,然后才可以检索和更新节点信息。Android完全支持DOM 解析。利用DOM中的对象,可以对XML文档进行读取、搜索、修改、添加和删除等操作。

DOM的工作原理:使用DOM对XML文件进行操作时,首先要解析文件,将文件分为独立的元素、属性和注释等,然后以节点树的形式在内存中对XML文件进行表示,就可以通过节点树访问文档的内容,并根据需要修改文档。

常用的DOM的接口和类:

Document:该接口定义分析并创建DOM文档的一系列方法,它是文档树的根,是操作DOM的基础。

Node:该接口提供处理并获取节点和子节点值的方法。

Element:该接口继承Node接口,提供了获取、修改XML元素名字和属性的方法。

NodeList:提供获得节点个数和当前节点的方法。这样就可以迭代地访问各个节点。

DOMParser:该类是Apache的Xerces中的DOM解析器类,可直接解析XML文件。

2、SAX解析

SAX(Simple API for XML) 使用流式处理的方式,它并不记录所读内容的相关信息。它是一种以事件为驱动的XML API,解析速度快,占用内存少。使用回调函数来实现。 缺点是因为以事件为驱动的它不能回退。

它的核心是事件处理模式,主要是围绕着事件源以及事件处理器来工作的。当事件源产生事件后,调用事件处理器相应的处理方法,一个事件就可以得到处理。在事件源调用事件处理器中特定方法的时候,还要传递给事件处理器相应事件的状态信息,这样事件处理器才能够根据提供的事件信息来决定自己的行为。

SAX的工作原理:SAX会顺序扫描文档,在扫描到文档(document)开始与结束、元素(element)开始与结束、元素内容(characters)等时通知事件处理方法,事件处理方法进行相应处理,然后继续扫描,指导文档扫描结束。

常用的SAX接口和类:

Attrbutes:用于得到属性的个数、名字和值。

ContentHandler:定义与文档本身关联的事件(例如,开始和结束标记)。大多数应用程序都注册这些事件。

DTDHandler:定义与DTD关联的事件。它没有定义足够的事件来完整地报告DTD。如果需要对DTD进行语法分析,请使用可选的DeclHandler。

DeclHandler是SAX的扩展。不是所有的语法分析器都支持它。

EntityResolver:定义与装入实体关联的事件。只有少数几个应用程序注册这些事件。

ErrorHandler:定义错误事件。许多应用程序注册这些事件以便用它们自己的方式报错。

DefaultHandler:它提供了这些接LI的缺省实现。在大多数情况下,为应用程序扩展DefaultHandler并覆盖相关的方法要比直接实现一个接口更容易。

下面是部分说明:

fd16011c704dSAX处理器说明

fd16011c704d

部分常用方法说明

所以,我们通常要使用XmlReader和DefaultHandler配合起来解析xml文档。

SAX的解析流程:

startDocument --> startElement --> characters --> endElement --> endDocument

3、pull解析

Pull内置于Android系统中。也是官方解析布局文件所使用的方式。Pull与SAX有点类似,都提供了类似的事件,如开始元素和结束元素。不同的是,SAX的事件驱动是回调相应方法,需要提供回调的方法,而后在SAX内部自动调用相应的方法。而Pull解析器并没有强制要求提供触发的方法。因为他触发的事件不是一个方法,而是一个数字。它使用方便,效率高。Android官方推荐开发者们使用Pull解析技术。Pull解析技术是第三方开发的开源技术,它同样可以应用于JavaSE开发。

pull返回的常量:

读取到xml的声明返回 START_DOCUMENT;

读取到xml的结束返回 END_DOCUMENT ;

读取到xml的开始标签返回 START_TAG;

读取到xml的结束标签返回 END_TAG;

读取到xml的文本返回 TEXT;

pull的工作原理:pull提供了开始元素和结束元素。当某个元素开始时,我们可以调用parser.nextText从XML文档中提取所有字符数据。当解释到一个文档结束时,自动生成EndDocument事件。

常用的XML pull的接口和类:

XmlPullParser:XML pull解析器是一个在XMLPULL VlAP1中提供了定义解析功能的接口。

XmlSerializer:它是一个接口,定义了XML信息集的序列。

XmlPullParserFactory:这个类用于在XMPULL V1 API中创建XML Pull解析器。

XmlPullParserException:抛出单一的XML pull解析器相关的错误。

pull的解析流程:

start_document --> end_document --> start_tag -->end_tag

**在Android中还有第四种方式:android.util.Xml类 **(本人未使用过)

在Android API中,另外提供了Android.util.Xml类,同样可以解析XML文件,使用方法类似SAX,也都需编写Handler来处理XML的解析,但是在使用上却比SAX来得简单 ,如下所示:

以android.util.XML实现XML解析 :

MyHandler myHandler=new MyHandler0;

android.util.Xm1.parse(url.openC0nnection().getlnputStream(),Xml.Encoding.UTF-8,myHandler);

代码讲解

了解完概念,我们就可以着手解析xml文件了。接下来我来讲述以下解析xml文件的步骤。

将xml文件放在main->assets目录下。

新建一个类XmlParserHandler继承DefaultHandler,并实现相关方法。代码如下:

xml文件:

......

XmlParserHandler类代码:

package com.example.cne_shop.bean.city;

import android.util.Log;

import com.example.cne_shop.bean.city.model.CityModel;

import com.example.cne_shop.bean.city.model.DistrictModel;

import com.example.cne_shop.bean.city.model.PrivinceModel;

import org.xml.sax.Attributes;

import org.xml.sax.SAXException;

import org.xml.sax.helpers.DefaultHandler;

import java.util.ArrayList;

import java.util.List;

import static android.content.ContentValues.TAG;

/**

* Created by 博 on 2017/7/27.

*/

public class XmlParserHandler extends DefaultHandler {

private List privinceModels ;

private List cityModels ;

private List districtModels ;

private PrivinceModel privinceModel ;

private DistrictModel districtModel ;

private CityModel cityModel ;

private String preTag ;

public List getPrivinceModels() {

return privinceModels;

}

@Override

public void startDocument() throws SAXException {

super.startDocument();

privinceModels = new ArrayList<>() ;

Log.d(TAG, "startDocument: ------------------------------");

//当读到第一个标签的时候会触发这个方法

}

@Override

public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {

super.startElement(uri, localName, qName, attributes);

//开始解析节点

if ("province".equals(localName)){

Log.d(TAG, "新建省: --------------------------------------------");

cityModels = new ArrayList<>() ;

privinceModel = new PrivinceModel() ;

privinceModel.setName(attributes.getValue("name") );

}else if ("city".equals(localName)){

districtModels = new ArrayList<>() ;

cityModel = new CityModel() ;

cityModel.setName(attributes.getValue("name") );

}else if ("district".equals(localName)){

districtModel = new DistrictModel() ;

districtModel.setName(attributes.getValue("name") );

districtModel.setZipcode(attributes.getValue("zipcode") );

}

preTag = localName ;

}

public void endDocument () {

//文档解析结束

Log.d(TAG, "endDocument: --------------------------------------------");

}

public void characters (char[] ch, int start, int length) {

//保存节点内容

if ("province".equals(preTag)){

privinceModels.add(privinceModel) ;

Log.d(TAG, "添加省: --------------------------------------------");

}else if ("city".equals(preTag)){

cityModels.add(cityModel) ;

privinceModel.setCityModels(cityModels);

Log.d(TAG, "添加市: --------------------------------------------");

}else if ("district".equals(preTag)){

districtModels.add(districtModel) ;

cityModel.setDistrictModels(districtModels);

Log.d(TAG, "添加县: --------------------------------------------");

}

preTag = null ;

}

public void endElement (String uri, String localName, String qName) {

//结束解析节点

Log.d(TAG, "endElement: ------------------------"+ uri + " " + localName + " " + qName);

}

}

调用新建类XmlParserHandler代码如下:

SAXParserFactory spf = SAXParserFactory.newInstance();

SAXParser sp = spf.newSAXParser();

XmlParserHandler sfh = new XmlParserHandler();

AssetManager am = this.getAssets();

InputStream is = am.open("province_data.xml");

sp.parse(is , sfh);

getAdrMsg(sfh.getPrivinceModels()) ;

地址选择器实现

pickerView简介

这是一款仿iOS的PickerView控件,有时间选择和选项选择,并支持一二三级联动,支持自定义样式,3.x新版本的详细特性如下:

有时间和选项这两种选择器

选项选择器支持三级联动

时间选择器支持起始和终止日期设定

支持“年,月,日,时,分,秒”,“省,市,区”等选项的单位(label)显示、隐藏和自定义。

支持自定义文字、颜色、文字大小等属性

支持背景颜色更换,有夜间模式需求的问题可以解决了

Item的文字长度过长时,文字会自适应缩放到Item的长度,避免显示不完全的问题

——TimePickerView 时间选择器,支持年月日时分,年月日,年月,时分等格式

——OptionsPickerView 选项选择器,支持一,二,三级选项选择,并且可以设置是否联动b2ecec739be8121665c9bf0add830221.gif

TimePickerNight.gif

JsonData.gif

Province.gif CustomLayout.gif

CustomLayout.gif

详细了解请戳github

pickerView代码调用

下面是地址选择器的代码调用

OptionsPickerView pvOptions = new OptionsPickerView.Builder(this, new OptionsPickerView.OnOptionsSelectListener() {

@Override

public void onOptionsSelect(int options1, int option2, int options3 ,View v) {

//返回的分别是三个级别的选中位置

consigneeAdr.setText(province.get(options1) + city.get(options1).get(option2) + county.get(options1).get(option2).get(options3));

zip_code = zip_codes.get(options1).get(option2).get(options3) ;

}

})

.setSubmitText("确定")//确定按钮文字

.setCancelText("取消")//取消按钮文字

.setTitleText("城市选择")//标题

.setSubCalSize(18)//确定和取消文字大小

.setTitleSize(20)//标题文字大小

.setTitleColor(Color.BLACK)//标题文字颜色

.setSubmitColor(Color.BLACK)//确定按钮文字颜色

.setCancelColor(Color.BLACK)//取消按钮文字颜色

.setTitleBgColor(Color.WHITE)//标题背景颜色 Night mode

.setBgColor(Color.WHITE)//滚轮背景颜色 Night mode

.setContentTextSize(18)//滚轮文字大小

// .setLinkage(false)//设置是否联动,默认true

.setLabels("", "", "")//设置选择的三级单位

.isCenterLabel(false) //是否只显示中间选中项的label文字,false则每项item全部都带有label。

.setCyclic(false, false, false)//循环与否

.setSelectOptions(1, 1, 1) //设置默认选中项

.setOutSideCancelable(false)//点击外部dismiss default true

.isDialog(true)//是否显示为对话框样式

.build();

// Log.d("----" , "--------------"+county.get(1).get(1).get(1)) ;

pvOptions.setPicker(province, city , county);//添加数据源

pvOptions.show();

没有什么要讲了的,都在注释里,这样我们就可以调用好玩的地址选择器啦。

其他部分没有什么要说的,就是简单布局,网络申请,处理信息,布拉布拉。完整代码请戳页首github地址。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值