系出名门Android(10) - HTTP 通信, XML 解析, 通过 Hander 实现异步消息处理

[索引页]
[源码下载]


系出名门Android(10) - HTTP 通信, XML 解析, 通过 Hander 实现异步消息处理


作者: webabcd


介绍
在 Android 中与服务端做 HTTP 通信,解析 XML,通过 Handler 实现异步消息处理
  • HTTP 通信 - 与服务端做 HTTP 通信,分别以 GET 方式和 POST 方式做演示
  • XML 解析 - 可以用两种方式解析 XML,分别是 DOM 方式和 SAX 方式
  • 异步消息处理 - 通过 Handler 实现异步消息处理,以一个自定义的异步下载类来说明 Handler 的用法 


1、HTTP 通信和 XML 解析的 Demo
MySAXHandler.java
package com.webabcd.communication; 

import org.xml.sax.Attributes; 
import org.xml.sax.SAXException; 
import org.xml.sax.helpers.DefaultHandler; 

// 继承 DefaultHandler 以实现指定 XML 的 SAX 解析器 
// DOM - W3C 标准,需要把 xml 数据全部加载完成后才能对其做解析,可对树做任意遍历 
// SAX - 流式解析,通过事件模型解析 xml,只能顺序解析 
public  class MySAXHandler  extends DefaultHandler { 

         private  boolean mIsTitleTag =  false
         private  boolean mIsSalaryTag =  false
         private  boolean mIsBirthTag =  false
         private String mResult = ""; 
         
         // 打开 xml 文档的回调函数 
        @Override 
         public  void startDocument()  throws SAXException { 
                 // TODO Auto-generated method stub 
                 super.startDocument(); 
        } 
         
         // 关闭 xml 文档的回调函数 
        @Override 
         public  void endDocument()  throws SAXException { 
                 // TODO Auto-generated method stub 
                 super.endDocument(); 
        } 
         
         // 一发现元素开始标记就回调此函数 
        @Override 
         public  void startElement(String uri, String localName, String qName, 
                        Attributes attributes)  throws SAXException { 
                 if (localName ==  "title"
                        mIsTitleTag =  true
                 else  if (localName ==  "salary"
                        mIsSalaryTag =  true
                 else  if (localName ==  "dateOfBirth"
                        mIsBirthTag =  true
                 else  if (localName ==  "employee"
                        mResult +=  "\nname:" + attributes.getValue( "name");         
        } 

         // 一发现元素结束标记就回调此函数 
        @Override 
         public  void endElement(String uri, String localName, String qName) 
                         throws SAXException { 
                 if (localName ==  "title"
                        mIsTitleTag =  false
                 else  if (localName ==  "salary"
                        mIsSalaryTag =  false
                 else  if (localName ==  "dateOfBirth"
                        mIsBirthTag =  false
        } 

         // 一发现元素值或属性值就回调此函数 
        @Override 
         public  void characters( char[] ch,  int start,  int length) 
                         throws SAXException { 
                 if (mIsTitleTag) 
                        mResult +=  new String(ch, start, length); 
                 else  if (mIsSalaryTag) 
                        mResult +=  " salary:" +  new String(ch, start, length); 
                 else  if (mIsBirthTag) 
                        mResult +=  " dateOfBirth:" +  new String(ch, start, length); 
        } 
         
         public String getResult(){ 
                 return mResult; 
        } 
}
 
Main.java
package com.webabcd.communication; 

import java.io.BufferedInputStream; 
import java.io.BufferedReader; 
import java.io.IOException; 
import java.io.InputStream; 
import java.io.InputStreamReader; 
import java.net.HttpURLConnection; 
import java.net.URL; 
import java.net.URLConnection; 
import java.util.ArrayList; 
import java.util.HashMap; 
import java.util.Map; 

import javax.xml.parsers.DocumentBuilder; 
import javax.xml.parsers.DocumentBuilderFactory; 
import javax.xml.parsers.SAXParser; 
import javax.xml.parsers.SAXParserFactory; 

import org.apache.http.HttpEntity; 
import org.apache.http.HttpResponse; 
import org.apache.http.client.entity.UrlEncodedFormEntity; 
import org.apache.http.client.methods.HttpPost; 
import org.apache.http.impl.client.DefaultHttpClient; 
import org.apache.http.message.BasicNameValuePair; 
import org.apache.http.protocol.HTTP; 
import org.apache.http.util.ByteArrayBuffer; 
import org.apache.http.util.EncodingUtils; 
import org.w3c.dom.Document; 
import org.w3c.dom.Element; 
import org.w3c.dom.NodeList; 
import org.xml.sax.InputSource; 
import org.xml.sax.XMLReader; 

import android.app.Activity; 
import android.os.Bundle; 
import android.view.View; 
import android.widget.Button; 
import android.widget.TextView; 

public  class Main  extends Activity { 
         
         private TextView textView; 
         
         /** Called when the activity is first created. */ 
        @Override 
         public  void onCreate(Bundle savedInstanceState) { 
                 super.onCreate(savedInstanceState); 
                setContentView(R.layout.main); 
                 
                textView = (TextView)  this.findViewById(R.id.textView); 
                 
                Button btn1 = (Button)  this.findViewById(R.id.btn1); 
                btn1.setText( "http get demo"); 
                btn1.setOnClickListener( new Button.OnClickListener() { 
                         public  void onClick(View v) { 
                                httpGetDemo(); 
                        } 
                }); 
                 
                Button btn2 = (Button)  this.findViewById(R.id.btn2); 
                btn2.setText( "http post demo"); 
                btn2.setOnClickListener( new Button.OnClickListener() { 
                         public  void onClick(View v) { 
                                httpPostDemo(); 
                        } 
                }); 
                 
                Button btn3 = (Button)  this.findViewById(R.id.btn3); 
                 // DOM - Document Object Model 
                btn3.setText( "DOM 解析 XML"); 
                btn3.setOnClickListener( new Button.OnClickListener() { 
                         public  void onClick(View v) { 
                                DOMDemo(); 
                        } 
                }); 
                 
                Button btn4 = (Button)  this.findViewById(R.id.btn4); 
                 // SAX - Simple API for XML 
                btn4.setText( "SAX 解析 XML"); 
                btn4.setOnClickListener( new Button.OnClickListener() { 
                         public  void onClick(View v) { 
                                SAXDemo(); 
                        } 
                }); 
        } 
         
         // Android 调用 http 协议的 get 方法 
         // 本例:以 http 协议的 get 方法获取远程页面响应的内容 
         private  void httpGetDemo(){ 
                 try { 
                         // 模拟器测试时,请使用外网地址 
                        URL url =  new URL( "http://xxx.xxx.xxx"); 
                        URLConnection con = url.openConnection(); 
                         
                        String result = "http status code: " + ((HttpURLConnection)con).getResponseCode() + "\n"
                        // HttpURLConnection.HTTP_OK 
                         
                        InputStream is = con.getInputStream(); 
                        BufferedInputStream bis = new BufferedInputStream(is); 
                        ByteArrayBuffer bab = new ByteArrayBuffer(32); 
                        int current = 0; 
                        while ( (current = bis.read()) != -1 ){ 
                                bab.append((byte)current); 
                        } 
                        result += EncodingUtils.getString(bab.toByteArray(), HTTP.UTF_8); 
                         
                        bis.close(); 
                        is.close(); 

                        textView.setText(result); 
                } catch (Exception e) { 
                        textView.setText(e.toString()); 
                } 
        } 
         
        // Android 调用 http 协议的 post 方法 
        // 本例:以 http 协议的 post 方法向远程页面传递参数,并获取其响应的内容 
        private void httpPostDemo(){ 
                try { 
                        // 模拟器测试时,请使用外网地址 
                        String url = "http://5billion.com.cn/post.php"; 
                        Map<String, String> data = new HashMap<String, String>(); 
                        data.put("name""webabcd"); 
                        data.put("salary""100"); 
                         
                        DefaultHttpClient httpClient = new DefaultHttpClient(); 
                        HttpPost httpPost = new HttpPost(url); 
                        ArrayList<BasicNameValuePair> postData = new ArrayList<BasicNameValuePair>(); 
                        for (Map.Entry<String, String> m : data.entrySet()) { 
                                postData.add(new BasicNameValuePair(m.getKey(), m.getValue())); 
                        } 

                        UrlEncodedFormEntity entity = new UrlEncodedFormEntity(postData, HTTP.UTF_8); 
                        httpPost.setEntity(entity); 
                         
                        HttpResponse response = httpClient.execute(httpPost); 
                         
                        String result = "http status code: " + response.getStatusLine().getStatusCode() + "\n"
                        // HttpURLConnection.HTTP_OK 
                         
                        HttpEntity httpEntity = response.getEntity(); 
                         
                        InputStream is = httpEntity.getContent(); 
                        result += convertStreamToString(is); 
                         
                        textView.setText(result); 
                } catch (Exception e) { 
                        textView.setText(e.toString());         
                } 
        } 
         
        // 以 DOM 方式解析 XML(xml 数据详见 res/raw/employee.xml) 
        private void DOMDemo(){ 
                try        { 
                        DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance(); 
                        DocumentBuilder docBuilder = docFactory.newDocumentBuilder(); 
                        Document doc = docBuilder.parse(this.getResources().openRawResource(R.raw.employee)); 
                        Element rootElement = doc.getDocumentElement(); 
                        NodeList employeeNodeList = rootElement.getElementsByTagName("employee"); 
                         
                        textView.setText("DOMDemo" + "\n"); 
                        String title = rootElement.getElementsByTagName("title").item(0).getFirstChild().getNodeValue(); 
                        textView.append(title); 
                        for (int i=0; i<employeeNodeList.getLength(); i++){ 
                                Element employeeElement = ((Element)employeeNodeList.item(i)); 
                                String name = employeeElement.getAttribute("name"); 
                                String salary = employeeElement.getElementsByTagName("salary").item(0).getFirstChild().getNodeValue(); 
                                String dateOfBirth = employeeElement.getElementsByTagName("dateOfBirth").item(0).getFirstChild().getNodeValue(); 
                                textView.append("\nname: "+name+" salary: "+salary+" dateOfBirth: " + dateOfBirth); 
                        } 
                } catch (Exception e) { 
                        textView.setText(e.toString());         
                } 
        } 
         
        // 以 SAX 方式解析 XML(xml 数据详见 res/raw/employee.xml) 
        // SAX 解析器的实现详见 MySAXHandler.java 
        private void SAXDemo(){ 
                try        { 
                        SAXParserFactory saxFactory = SAXParserFactory.newInstance(); 
                        SAXParser parser = saxFactory.newSAXParser(); 
                        XMLReader reader = parser.getXMLReader(); 
                         
                        MySAXHandler handler = new MySAXHandler(); 
                        reader.setContentHandler(handler); 
                        reader.parse(new InputSource(this.getResources().openRawResource(R.raw.employee))); 
                        String result = handler.getResult(); 
                        textView.setText("SAXDemo" + "\n"); 
                        textView.append(result); 
                } catch (Exception e) { 
                        textView.setText(e.toString());         
                } 
        } 

        // 辅助方法,用于把流转换为字符串 
        private String convertStreamToString(InputStream is) { 
                BufferedReader reader = new BufferedReader(new InputStreamReader(is)); 
                StringBuilder sb = new StringBuilder();        

                String line = null
                try { 
                        while ((line = reader.readLine()) != null) { 
                                sb.append(line + "\n"); 
                        } 
                } catch (IOException e) { 
                        e.printStackTrace(); 
                } finally { 
                        try { 
                                is.close(); 
                        } catch (IOException e) { 
                                e.printStackTrace(); 
                        } 
                }        

                return sb.toString(); 
        } 
}
 
 
2、用 Handler 来实现异步消息处理,以一个可以实时汇报下载进度的异步下载类为例
开发一个 Android 类库,本例中此类库名为 webabcd_util

New -> Java Project
项目上点右键 -> Build Path -> Add Libraries -> User Library -> User Libraries -> New -> 为类库起个名字 -> 选中这个类库 -> Add JARs 导入 Android 的 jar 包
项目上点右键 -> Build Path -> Add Libraries -> User Library -> 选择 Android 库

DownloadManagerAsync.java
package webabcd.util; 

import java.io.BufferedReader; 
import java.io.File; 
import java.io.FileOutputStream; 
import java.io.InputStream; 
import java.io.InputStreamReader; 
import java.net.URL; 
import java.net.URLConnection; 

import org.apache.http.protocol.HTTP; 

import android.os.Handler; 
import android.os.Message; 
import android.util.Log; 

// 以一个实例,即异步下载,来演示 Android 的异步消息处理(用 Handler 的方式) 
public  class DownloadManagerAsync { 

         public DownloadManagerAsync() { 

        } 

         // 实例化自定义的 Handler 
        EventHandler mHandler =  new EventHandler( this); 

         // 按指定 url 地址下载文件到指定路径 
         public  void download( final String url,  final String savePath) { 
                 new Thread( new Runnable() { 
                         public  void run() { 
                                 try { 
                                        sendMessage(FILE_DOWNLOAD_CONNECT); 
                                        URL sourceUrl =  new URL(url); 
                                        URLConnection conn = sourceUrl.openConnection(); 
                                        InputStream inputStream = conn.getInputStream(); 

                                         int fileSize = conn.getContentLength(); 

                                        File savefile =  new File(savePath); 
                                         if (savefile.exists()) { 
                                                savefile.delete(); 
                                        } 
                                        savefile.createNewFile(); 

                                        FileOutputStream outputStream =  new FileOutputStream( 
                                                        savePath,  true); 

                                         byte[] buffer =  new  byte[1024]; 
                                         int readCount = 0; 
                                         int readNum = 0; 
                                         int prevPercent = 0; 
                                         while (readCount < fileSize && readNum != -1) { 
                                                readNum = inputStream.read(buffer); 
                                                 if (readNum > -1) { 
                                                        outputStream.write(buffer); 
                                                        readCount = readCount + readNum; 

                                                         int percent = ( int) (readCount * 100 / fileSize); 
                                                         if (percent > prevPercent) { 
                                                                 // 发送下载进度信息 
                                                                sendMessage(FILE_DOWNLOAD_UPDATE, percent, 
                                                                                readCount); 

                                                                prevPercent = percent; 
                                                        } 
                                                } 
                                        } 

                                        outputStream.close(); 
                                        sendMessage(FILE_DOWNLOAD_COMPLETE, savePath); 

                                }  catch (Exception e) { 
                                        sendMessage(FILE_DOWNLOAD_ERROR, e); 
                                        Log.e( "MyError", e.toString()); 
                                } 
                        } 
                }).start(); 
        } 

         // 读取指定 url 地址的响应内容 
         public  void download( final String url) { 
                 new Thread( new Runnable() { 
                         public  void run() { 
                                 try { 
                                        sendMessage(FILE_DOWNLOAD_CONNECT); 
                                        URL sourceUrl =  new URL(url); 
                                        URLConnection conn = sourceUrl.openConnection(); 
                                        conn.setConnectTimeout(3000); 
                                        BufferedReader reader =  new BufferedReader( 
                                                         new InputStreamReader(conn.getInputStream(), 
                                                                        HTTP.UTF_8)); 

                                        String line =  null
                                        StringBuffer content =  new StringBuffer(); 
                                         while ((line = reader.readLine()) !=  null) { 
                                                content.append(line); 
                                        } 

                                        reader.close(); 

                                        sendMessage(FILE_DOWNLOAD_COMPLETE, content.toString()); 

                                }  catch (Exception e) { 
                                        sendMessage(FILE_DOWNLOAD_ERROR, e); 
                                        Log.e( "MyError", e.toString()); 
                                } 
                        } 
                }).start(); 
        } 

         // 向 Handler 发送消息 
         private  void sendMessage( int what, Object obj) { 
                 // 构造需要向 Handler 发送的消息 
                Message msg = mHandler.obtainMessage(what, obj); 
                 // 发送消息 
                mHandler.sendMessage(msg); 
        } 

         private  void sendMessage( int what) { 
                Message msg = mHandler.obtainMessage(what); 
                mHandler.sendMessage(msg); 
        } 

         private  void sendMessage( int what,  int arg1,  int arg2) { 
                Message msg = mHandler.obtainMessage(what, arg1, arg2); 
                mHandler.sendMessage(msg); 
        } 

         private  static  final  int FILE_DOWNLOAD_CONNECT = 0; 
         private  static  final  int FILE_DOWNLOAD_UPDATE = 1; 
         private  static  final  int FILE_DOWNLOAD_COMPLETE = 2; 
         private  static  final  int FILE_DOWNLOAD_ERROR = -1; 

         // 自定义的 Handler 
         private  class EventHandler  extends Handler { 
                 private DownloadManagerAsync mManager; 

                 public EventHandler(DownloadManagerAsync manager) { 
                        mManager = manager; 
                } 

                 // 处理接收到的消息 
                @Override 
                 public  void handleMessage(Message msg) { 

                         switch (msg.what) { 
                         case FILE_DOWNLOAD_CONNECT: 
                                 if (mOnDownloadConnectListener !=  null
                                        mOnDownloadConnectListener.onDownloadConnect(mManager); 
                                 break
                         case FILE_DOWNLOAD_UPDATE: 
                                 if (mOnDownloadUpdateListener !=  null
                                        mOnDownloadUpdateListener.onDownloadUpdate(mManager, 
                                                        msg.arg1); 
                                 break
                         case FILE_DOWNLOAD_COMPLETE: 
                                 if (mOnDownloadCompleteListener !=  null
                                        mOnDownloadCompleteListener.onDownloadComplete(mManager, 
                                                        msg.obj); 
                                 break
                         case FILE_DOWNLOAD_ERROR: 
                                 if (mOnDownloadErrorListener !=  null
                                        mOnDownloadErrorListener.onDownloadError(mManager, 
                                                        (Exception) msg.obj); 
                                 break
                         default
                                 break
                        } 
                } 
        } 

         // 定义连接事件 
         private OnDownloadConnectListener mOnDownloadConnectListener; 
         public  interface OnDownloadConnectListener { 
                 void onDownloadConnect(DownloadManagerAsync manager); 
        } 
         public  void setOnDownloadConnectListener(OnDownloadConnectListener listener) { 
                mOnDownloadConnectListener = listener; 
        } 

         // 定义下载进度更新事件 
         private OnDownloadUpdateListener mOnDownloadUpdateListener; 
         public  interface OnDownloadUpdateListener { 
                 void onDownloadUpdate(DownloadManagerAsync manager,  int percent); 
        } 
         public  void setOnDownloadUpdateListener(OnDownloadUpdateListener listener) { 
                mOnDownloadUpdateListener = listener; 
        } 

         // 定义下载完成事件 
         private OnDownloadCompleteListener mOnDownloadCompleteListener; 
         public  interface OnDownloadCompleteListener { 
                 void onDownloadComplete(DownloadManagerAsync manager, Object result); 
        } 
         public  void setOnDownloadCompleteListener( 
                        OnDownloadCompleteListener listener) { 
                mOnDownloadCompleteListener = listener; 
        } 

         // 定义下载异常事件 
         private OnDownloadErrorListener mOnDownloadErrorListener; 
         public  interface OnDownloadErrorListener { 
                 void onDownloadError(DownloadManagerAsync manager, Exception e); 
        } 
         public  void setOnDownloadErrorListener(OnDownloadErrorListener listener) { 
                mOnDownloadErrorListener = listener; 
        } 
}
 
调用上面的自定义的 Android 类库

项目上点右键 -> Properties -> Java Build Path -> Projects -> Add 引用上面的类库

Main.java
package com.webabcd.handler; 

import android.app.Activity; 
import android.os.Bundle; 
import android.widget.TextView; 

import webabcd.util.DownloadManagerAsync; 

public  class Main  extends Activity  implements 
                DownloadManagerAsync.OnDownloadCompleteListener, 
                DownloadManagerAsync.OnDownloadUpdateListener, 
                DownloadManagerAsync.OnDownloadErrorListener { 
         
        TextView txt; 
         
         /** Called when the activity is first created. */ 
        @Override 
         public  void onCreate(Bundle savedInstanceState) { 
                 super.onCreate(savedInstanceState); 
                setContentView(R.layout.main); 
                 
                DownloadManagerAsync manager =  new DownloadManagerAsync(); 
                manager.setOnDownloadCompleteListener( this); 
                manager.setOnDownloadUpdateListener( this); 
                manager.download( "http://files.cnblogs.com/webabcd/Android.rar", "/sdcard/Android.rar"); 
                 
                txt = (TextView) this.findViewById(R.id.txt); 
                txt.setText("开始下载"); 
        } 

        public void onDownloadComplete(DownloadManagerAsync manager, Object result) { 

                txt.setText("下载完成"); 
        } 
         
        public void onDownloadUpdate(DownloadManagerAsync manager, int percent) { 

                txt.setText("下载进度:" + String.valueOf(percent) + "%"); 
        } 
         
        public void onDownloadError(DownloadManagerAsync manager, Exception e) { 

                txt.setText("下载出错"); 
        } 
}
 


     本文转自webabcd 51CTO博客,原文链接: http://blog.51cto.com/webabcd/342102 ,如需转载请自行联系原作者


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值