系出名门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(
" 下载出错 " );
    }
}


OK
[源码下载]
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值