Android中使用sax解析XML

来源:互联网 发布:php 工厂模式 实例 编辑:程序博客网 时间:2024/05/01 02:18

            在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);
        }
    };

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

大家别见笑啊,呵呵。





原创粉丝点击