您的位置:首页 > 移动开发 > Android开发

Android中使用sax解析XML

2012-04-08 14:25 447 查看
在Android中使用XML解析数据是非常常见的一件事,但是使用那种方式比较好呢,因为基于Android开发的硬件毕竟性能一般有限,主要是手机和嵌入式设备。一般我们使用sax解析。速度比较快,也不大耗内存。当然负面影响也是有的,编码比较多,而且比较复杂些。下面我们来看一个例子:

首先我们实现一个xml的实体类,如下:

//收藏明细实体类

public class TPFavouriteItemModel {

public static String SN = "sn";

public static String IMAGEURL = "productimageurl";

public static String NAME = "productname";

public static String PRICE="productprice";

//产品ID

private String Sn;

//产品图片路径

private String ProductImageUrl;

//产品名称

private String ProductName;

//产品价格

private String ProductPrice;

//Construct Function

public TPFavouriteItemModel() {

}

//Construct Function

public TPFavouriteItemModel(String sn,String imageUrl, String name,String price) {

this.Sn=sn;

this.ProductImageUrl = imageUrl;

this.ProductName = name;

this.ProductPrice=price;

}

//获取产品ID

public String getProductID()

{

return Sn;

}

//获取产品图片路径

public String getProductImageUrl() {

return ProductImageUrl;

}

//获取产品名称

public String getProductName() {

return ProductName;

}

//获取产品价格

public String getProductPrice() {

return ProductPrice;

}

//设置产品图片路径

public void setProductID(String str) {

Sn=str;

}

//设置产品图片路径

public void setProductImageUrl(String str)

{

ProductImageUrl=str;

}

//设置产品名称

public void setProductName(String str)

{

ProductName=str;

}

//设置产品价格

public void setProductPrice(String str)

{

ProductPrice=str;

}

}

其次我们要实现一个对应的Handler类来处理xml文档,这里面定义了很多xml文档的事件,代码如下:

//收藏夹明细handler

public class TPFavouriteItemHandler extends DefaultHandler {

TPFavouriteItemModel favouriteItem;

TPFavouriteItemFeed favouriteFeed;

//收藏夹明细数据类中的变量状态

final int CI_PRODUCTID=1;

final int CI_PRODUCTIMAGEURL=2;

final int CI_PRODUCTNAME=3;

final int CI_PRODUCTPRICE=4;

int currentstate = 0;

//收藏夹构造类

public TPFavouriteItemHandler()

{

}

//获取收藏夹填充类

public TPFavouriteItemFeed getCartFeed()

{

return favouriteFeed;

}

@Override

public void startDocument() throws SAXException {

// TODO Auto-generated method stub

favouriteItem = new TPFavouriteItemModel();

favouriteFeed = new TPFavouriteItemFeed();

}

@Override

public void endDocument() throws SAXException {

// TODO Auto-generated method stub

}

@Override

public void startElement(String uri, String localName, String qName,

Attributes attributes) throws SAXException {

// TODO Auto-generated method stub

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

currentstate = 0;

return;

}

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

favouriteItem = new TPFavouriteItemModel();

return;

}

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

currentstate = CI_PRODUCTID;

return;

}

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

currentstate = CI_PRODUCTIMAGEURL;

return;

}

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

currentstate = CI_PRODUCTNAME;

return;

}

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

currentstate = CI_PRODUCTPRICE;

return;

}

currentstate = 0;

}

@Override

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

throws SAXException {

// TODO Auto-generated method stub

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

favouriteFeed.addItem(favouriteItem);

return;

}

}

//填充值

@Override

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

throws SAXException {

// TODO Auto-generated method stub

String theString = new String(ch, start, length);

switch(currentstate){

case CI_PRODUCTID:

favouriteItem.setProductID(theString);

currentstate = 0;

break;

case CI_PRODUCTIMAGEURL:

favouriteItem.setProductImageUrl(theString);

currentstate = 0;

break;

case CI_PRODUCTNAME:

favouriteItem.setProductName(theString);

currentstate = 0;

break;

case CI_PRODUCTPRICE:

favouriteItem.setProductPrice(theString);

currentstate = 0;

break;

default:

return;

}

}

接下来我们要实现一个对应的Adapter类,因为我们是要解析一个收藏夹的xml文档,代码如下:

public class FavourityListAdapter extends ArrayAdapter<TPFavouriteItemModel> {

private ListView listView;

private AsyncImageLoader asyncImageLoader;

public FavourityListAdapter(Activity activity, List<TPFavouriteItemModel> favourites, ListView listView) {

super(activity, 0, favourites);

this.listView = listView;

asyncImageLoader = new AsyncImageLoader();

}

public View getView(int position, View convertView, ViewGroup parent) {

Activity activity = (Activity) getContext();

// Inflate the views from XML

View rowView = convertView;

ViewCache viewCache;

if (rowView == null) {

LayoutInflater inflater = activity.getLayoutInflater();

rowView = inflater.inflate(R.layout.favourite_item, null);

viewCache = new ViewCache(rowView);

rowView.setTag(viewCache);

} else {

viewCache = (ViewCache) rowView.getTag();

}

TPFavouriteItemModel favouriteItem = getItem(position);

// Load the image and set it on the ImageView

String imageUrl = favouriteItem.getProductImageUrl();

ImageView imageView = viewCache.getPruductImageView();

imageView.setTag(imageUrl);

Drawable cachedImage = asyncImageLoader.loadDrawable(imageUrl, new ImageCallback() {

public void imageLoaded(Drawable imageDrawable, String imageUrl) {

ImageView imageViewByTag = (ImageView) listView.findViewWithTag(imageUrl);

if (imageViewByTag != null) {

imageViewByTag.setImageDrawable(imageDrawable);

}

}

});

if (cachedImage == null) {

imageView.setImageResource(R.drawable.default_image);

}else{

imageView.setImageDrawable(cachedImage);

}

// Set the text on the Product Name

TextView tvName = viewCache.getProductNameView();

tvName.setText(favouriteItem.getProductName());

// Set the text on the Product Price

TextView tvPrice = viewCache.getProductPriceView();

tvPrice.setText(favouriteItem.getProductPrice());

return rowView;

}

}

因为收藏夹中包括图片显示,而图片加载可能会比较慢,为了取得比较好的用户体验我们要采用异步

方式加载,因此我们定义了一个AsyncImageLoader类,它的具体实现如下所示:

public class AsyncImageLoader {

private HashMap<String, SoftReference<Drawable>> imageCache;

public AsyncImageLoader() {

imageCache = new HashMap<String, SoftReference<Drawable>>();

}

public Drawable loadDrawable(final String imageUrl, final ImageCallback imageCallback) {

if (imageCache.containsKey(imageUrl)) {

SoftReference<Drawable> softReference = imageCache.get(imageUrl);

Drawable drawable = softReference.get();

if (drawable != null) {

return drawable;

}

}

final Handler handler = new Handler() {

public void handleMessage(Message message) {

imageCallback.imageLoaded((Drawable) message.obj, imageUrl);

}

};

new Thread() {

@Override

public void run() {

Drawable drawable = loadImageFromUrl(imageUrl);

imageCache.put(imageUrl, new SoftReference<Drawable>(drawable));

Message message = handler.obtainMessage(0, drawable);

handler.sendMessage(message);

}

}.start();

return null;

}

public static Drawable loadImageFromUrl(String url) {

URL m;

InputStream i = null;

try {

m = new URL(url);

i = (InputStream) m.getContent();

} catch (MalformedURLException e1) {

e1.printStackTrace();

} catch (IOException e) {

e.printStackTrace();

}

Drawable d = Drawable.createFromStream(i, "src");

return d;

}

public interface ImageCallback {

public void imageLoaded(Drawable imageDrawable, String imageUrl);

}

}

接着我们来看看收藏夹的布局文件:

<?xml version="1.0" encoding="utf-8"?>

<!-- 我的收藏画面 -->

<LinearLayout

xmlns:android="http://schemas.android.com/apk/res/android"

android:layout_width="fill_parent"

android:layout_height="fill_parent">

<ListView android:id="@+id/lvFavourite" android:layout_width="wrap_content"

android:layout_height="fill_parent"

>

</ListView>

</LinearLayout>

下面这个是收藏夹的明细画面,放置在ListView中的:

<?xml version="1.0" encoding="utf-8"?>

<!-- 收藏夹画面的明细条目 -->

<LinearLayout

xmlns:android="http://schemas.android.com/apk/res/android"

android:layout_width="fill_parent" android:orientation="horizontal"

android:layout_height="fill_parent"

>

<LinearLayout android:id="@+id/llItem" android:layout_width="120dip"

android:layout_height="100dip" android:orientation="vertical">

<!-- 商品图片 -->

<ImageView android:id="@+id/ivProduct" android:layout_width="80dip"

android:layout_height="60dip"/>

<!-- 商品价格 -->

<TextView android:id="@+id/tvProductPrice" android:layout_width="wrap_content"

android:layout_height="40dip"/>

</LinearLayout>

<LinearLayout android:id="@+id/llItemProduct" android:layout_width="180dip"

android:layout_height="100dip"

>

<!-- 商品名称 -->

<TextView android:id="@+id/tvProductName" android:layout_width="wrap_content"

android:layout_height="100dip" android:layout_marginTop="60dip"/>

</LinearLayout>

<LinearLayout android:id="@+id/llItemIcon" android:layout_width="20dip"

android:layout_height="100dip"

>

<!--跳转图标-->

<ImageView android:id="@+id/ivIcon"

android:layout_width="12.0dip" android:layout_height="12.0dip"

android:layout_marginRight="2dip" android:layout_marginTop="60dip"

android:src="@drawable/into_icon" />

</LinearLayout>

</LinearLayout>

最后就是在Activity中的实现了:

ListView list;

private FavourityListAdapter favouritylistadapter;

private TPFavouriteItemFeed favouriteitemfeed;

private List<TPFavouriteItemModel> ltFavourite;

@Override

public void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.myfavourite);

Log.d("WineStock", "TP_MyFavouriteActivity onCreate");

if(!TPLoginUserInfo.hasLogin())

{

Log.d("WineStock", "please login first");

return;

}

try

{

list = (ListView) findViewById(R.id.lvFavourite);

ltFavourite = new ArrayList<TPFavouriteItemModel>();

// 获取我的收藏的列表

GetMyFavouriteItem();

list.setOnItemClickListener(clickViewBtn);

}

catch(Exception e)

{

Log.d("WineStock", "TP_MyFavouriteActivity onCreate Error:"+e.getMessage());

}

}

// 获取我的收藏夹信息

private void GetMyFavouriteItem() {

favouriteitemfeed = getFeed();

if (favouriteitemfeed == null) {

Log.d("WineStock", "访问失败...");

return;

} else {

try {

// 获取收藏夹中的数据

ltFavourite = favouriteitemfeed.getAllItemListForListView();

// 判断收藏夹是否为空

if (ltFavourite.size() > 0) {

Log.d("WineStock", "Login my favourite");

} else {

Log.d("WineStock", "Favourite is empty");

return;

}

favouritylistadapter = new FavourityListAdapter(this,

ltFavourite, list);

list.setAdapter(favouritylistadapter);

} catch (Exception e) {

Log.d("WineStock", "Fail to Set ListView,Error:" + e.getMessage());

}

}

}

// 获取收藏夹的xml文件

public TPFavouriteItemFeed getFeed() {

try {

// 这里我们实现了本地解析,所以注掉了这个取网络数据的。

Log.d("WineStock", "ready to get my favourite from net.");

SAXParserFactory factory = SAXParserFactory.newInstance();

SAXParser parser = factory.newSAXParser();

XMLReader reader = parser.getXMLReader();

TPFavouriteItemHandler handler = new TPFavouriteItemHandler();

reader.setContentHandler(handler);

String[] parameterList = new String[4];

// 这里只是暂时测试使用

parameterList[0] = "keyFavorites";

parameterList[1] = "US00000065";// TPLoginUserInfo.UserIdentify;

parameterList[2] = "10";

parameterList[3] = "0";

// 从webService获取数据

String strRemoteFavouriteItemInfo = GetFavouriteItemWS(

Config.METHOD_GETFAVOURITEINFO, parameterList);

if (strRemoteFavouriteItemInfo != null) {

InputStream inputStream = new ByteArrayInputStream(

strRemoteFavouriteItemInfo.getBytes());

InputSource is = new InputSource(inputStream);

reader.parse(is);

} else {

Log.d("WineStock",

"TPFavouriteItemFeed:Get Shopping cart item error");

}

return handler.getCartFeed();

} catch (ParserConfigurationException e) {

// TODO Auto-generated catch block

// e.printStackTrace();

Log.d("WineStock", "111ParserConfigurationException"

+ e.getMessage());

} catch (SAXException e) {

// TODO Auto-generated catch block

// e.printStackTrace();

Log.d("WineStock", "222SAXException" + e.getMessage());

} catch (IOException e) {

// TODO Auto-generated catch block

// e.printStackTrace();

Log.d("WineStock", "333IOException" + e.getMessage());

}

return null;

}

// 调用webservic来获取收藏夹的xml

private String GetFavouriteItemWS(String methodName, String[] parameterList) {

// 创建SoapObject对象,并指定WebService的命名空间和调用的方法名

SoapObject request = new SoapObject(Config.NAMESPACE, methodName);

// 调用的函数如果有参数,这里可以设置需要传递的参数 注意:第一个参数使用arg0 多个参数依次类推 arg1,arg2...

if (parameterList != null) {

request.addProperty("key", parameterList[0]);

request.addProperty("userID", parameterList[1]);

request.addProperty("dataCount", parameterList[2]);

request.addProperty("page", parameterList[3]);

}

// 生成调用WebService方法的SOAP请求信息,并指定SOAP的版本

SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(

SoapEnvelope.VER11);

// envelope.setOutputSoapObject(request);

// 上边的一句等价于下边的这句 将SoapObject对象赋给envelope对象

envelope.bodyOut = request;

// 当前开发的是Java WS 这里需要不调用.net WS

envelope.dotNet = true;

/*

* 这里不要使用 AndroidHttpTransport ht = new AndroidHttpTransport(URL);

* 这是一个要过期的类

* 创建HttpTransportSE对象。通过HttpTransportSE类的构造方法可以指定WebService的WSDL文档的URL

*/

HttpTransportSE ht = new HttpTransportSE(Config.GETFAVOURITEINFO);

try {

// 请求WS

ht.call(Config.SOAP_ACTION, envelope);

if (envelope.getResponse() != null) {

// 获得WS函数返回值信息

// System.out.println(envelope.getResponse().toString());

Log.d("WineStock", "GetFavouriteItemWS Result:"

+ envelope.getResponse().toString());

return envelope.getResponse().toString();

}

} catch (Exception e) {

e.printStackTrace();

System.out.println(e.getMessage());

Log.d("WineStock", "GetFavouriteItemWS Error:" + e.getMessage());

}

return null;

}

// 单击进入详细页面

OnItemClickListener clickViewBtn = new OnItemClickListener() {

public void onItemClick(AdapterView<?> parent, View view, int position,

long id) {

String goodssn = (String) ltFavourite.get(position).getProductID();

Intent intent = new Intent(TP_MyFavouriteActivity.this,

ProductsInfo.class);

Bundle bundle = new Bundle();

bundle.putString("GoodsSn", goodssn);

intent.putExtras(bundle);

startActivityInFrame(intent);

}

};

先只介绍这么多了,在这个画面的实现中其实还有分页和实现没有介绍,这里涉及的东西还是比较多的了。写的可能比较混乱,

大家别见笑啊,呵呵。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: