首页 > 代码库 > android学习二十四(网络编程的最佳实践)

android学习二十四(网络编程的最佳实践)



 前面的博客已经讲解了HttpURLConnection和HttpClient的用法,知道了如何发起HTTP请求,以及解析服务器返回
 的数据。但是可能你发现了,因为一个应用程序很多地方都可能使用网络功能,而发送HTTP请求的代码基本相同,如果每次我们都去编写一遍发送HTTP请求的代码,这显然不太好。
    通常情况下我们都应该将这些通用的网络操作提取到一个公共的类里,并提供一个静态方法,当想要发起网络请求的时候只需简单地调用一下这个方法即可。比如下面的写法:

package com.jack.networktest;

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;

public class HttpUtil {

	public static String sendHttpRequest(String address){
		HttpURLConnection connection=null;
		try{
			URL url=new URL(address);
			connection = (HttpURLConnection) url.openConnection();
			connection.setRequestMethod("GET");
			connection.setConnectTimeout(8000);
			connection.setReadTimeout(8000);
			connection.setDoInput(true);
			connection.setDoOutput(true);
			InputStream in=connection.getInputStream();
			BufferedReader reader=new BufferedReader(new InputStreamReader(in));
			StringBuilder response=new StringBuilder();
			String line;
			while((line=reader.readLine())!=null){
				response.append(line);
			}
			return response.toString();
		}catch(Exception e){
			e.printStackTrace();
			return e.getMessage();
		}finally{
			if(connection!=null){
				connection.disconnect();
			}
		}
	}
}


以后每当要发起一条HTTP请求的时候就可以这样写:
  String address="http://www.baidu.com";
  String response=HttpUtil.sendHttpRequest(address);


         在获取到服务器响应的数据后我们就可以对它进行解析和处理了。但是需要注意,网络请求通常都是属于耗时操作,而 sendHttpRequest方法的内部并没有开启线程,这样就可能导致在调用sendHttpRequest方法的时候使得主线程阻塞住。你可能说,在sendHttpRequest方法内部开启一个线程不就解决了阻塞这个问题了嘛。其实没那么简单,因为如果我们在sendHttpRequest方法中开启了一个线程来发起HTTP请求,那么服务器响应的数据是无法进行返回的,所有的耗时逻辑都是在子线程里进行的,sendHttpRequest方法会在服务器还来得及响应的时候就执行结束了,当然也就无法返回响应的数据了。
  那么这种情况该如何解决?其实解决方法可以使用java的回调机制,下面就让我们来学习一下回调机制到底如何使用的。
  首先需要定义一个接口,比如将它命名成HttpCallbackListener,代码如下所示:
  public interfac HttpCallbackListener{
  void onFinish(String response);
  void one rror(Exception e);
  }
  可以看到,我们在接口中定义了两个方法,onFinish(String response)方法表示当服务器成功响应我们请求
  的时候调用,onError(Exception e)表示当进行网络操作出现错误的时候调用。这两个方法都带有参数,
  onFinish(String response)方法中的参数代表着服务器返回的数据,而onError(Exception e)方法
  中的参数记录着错误的详细信息。

       接着修改HttpUtil中的代码:

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;

public class HttpUtil {

	public static void sendHttpRequest(final String address,
			final HttpCallbackListener listener){
		new Thread(new Runnable(){

			
			@Override
			public void run() {
				// TODO Auto-generated method stub
				HttpURLConnection connection=null;
				try{
					URL url=new URL(address);
					connection = (HttpURLConnection) url.openConnection();
					connection.setRequestMethod("GET");
					connection.setConnectTimeout(8000);
					connection.setReadTimeout(8000);
					connection.setDoInput(true);
					connection.setDoOutput(true);
					InputStream in=connection.getInputStream();
					BufferedReader reader=new BufferedReader(new InputStreamReader(in));
					StringBuilder response=new StringBuilder();
					String line;
					while((line=reader.readLine())!=null){
						response.append(line);
					}
					if(listener!=null){
						//回调onFinish()方法
						listener.onFinish(response.toString());
					}
				}catch(Exception e){
					if(listener!=null){
						//回调onError()方法
						listener.onError(e);
					}
					
				}finally{
					if(connection!=null){
						connection.disconnect();
					}
					}
			}
				}).start();
		
		
	}
}


我们首先给sendHttpRequest方法添加了一个HttpCallbackListener参数,并在方法的内部开启了一个子线程,然后
在子线程里去执行具体的网络操作。注意子线程中是无法通过return语句来返回数据的,因此这里我们将服务器响应的数据传入了HttpCallbackListener的onFinish()方法中,如果出现了异常就将异常原因传入到onError()方法中。
  现在sendHttpRequest方法接收两个参数了,因此我们在调用它的时候还需要将HttpCallbackListener的实例传入
  如下所示:

HttpUtil.sendHttpRequest(address,new HttpCallbackListener(){
   public void onFinish(String response){
   //在这里根据返回内容执行具体的逻辑
   }
   
   public void one rror(Exception e){
      //在这里对异常进行处理
   }
   
  });


这样的话,当服务器成功响应的时候我们就可以在onFinish方法里对响应数据进行处理了,类似地,如果出现了异常,就可以在onError方法里对异常情况进行处理。如此一来,我们就巧妙的利用回调机制将响应数据成功返回给调用方了。
  另外需要注意的是,onFinish方法和onError方法最终还是在子线程中运行的,因此我们不可以在这里执行任何的
  UI操作,如果需要根据返回的结果来更新UI,则仍然要使用异步消息处理机制。




http://blog.csdn.net/j903829182/article/details/42521437



android学习二十四(网络编程的最佳实践)