在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);
}
};
先只介绍这么多了,在这个画面的实现中其实还有分页和实现没有介绍,这里涉及的东西还是比较多的了。写的可能比较混乱,
大家别见笑啊,呵呵。