andriod开发,简单的封装网络请求并监听返回.

一.为什么封装

因为android 4.0 以后的发送网络请求必须要放到异步线程中,而异步线程必须跟handle合作才能更新主线程中的UI,所以建议用一个类继承handler来异步处理网络请求.

二.封装哪些功能.

首先,每次发送网络请求都需要先检测网络连接是否正常.其次需要向用户提供一个提示信息,比如ProgressDialog,然后简单粗暴的把网络请求结果设为3种:1->请求成功;2->请求失败;3->连接超时.请求成功的话就返回正确的结果,请求失败就提示网络请求失败.请求超时就询问是否重连.所以需要封装的就有:

1.检测网络

/**
	 * 判断网络连接
	 */
	private boolean isNetworkConnect() {
		ConnectivityManager cm = (ConnectivityManager) activity
				.getSystemService(Context.CONNECTIVITY_SERVICE);
		cm.getActiveNetworkInfo();
		if (cm.getActiveNetworkInfo() != null) {
			return cm.getActiveNetworkInfo().isAvailable();
		}
		return false;
	}

	/**
	 * 打开网络对话框
	 */
	private void whetherOpenNet() {
		if (dialog != null) {
			dialog.cancel();
			dialog = null;
		}
		AlertDialog.Builder builder = new AlertDialog.Builder(activity);
		builder.setTitle("网络木有连接");
		builder.setMessage("是否打开网络连接");
		builder.setPositiveButton("确定", new DialogInterface.OnClickListener() {

			@Override
			public void onClick(DialogInterface dialog, int which) {
				activity.startActivityForResult(new Intent(
						Settings.ACTION_WIRELESS_SETTINGS), OPEN_NETWORK);
			}
		});
		builder.setNegativeButton("取消", null);
		dialog = builder.create();
		dialog.show();
	}

2.进度条提示

/**
	 * 显示进度条提示
	 * 
	 * @param message
	 */
	private void showPd(String message) {
		showLog("start connect");
		if (message == null || message.length() == 0) {
			return;
		}
		if (pd != null) {
			pd.cancel();
			pd = null;
		}
		pd = new ProgressDialog(activity);
		pd.setMessage(message);
		pd.setOnCancelListener(new OnCancelListener() {

			@Override
			public void onCancel(DialogInterface dialog) {
				requestThread.interrupt();
			}
		});
		pd.setCancelable(true);
		pd.show();
	}

3.处理请求结果

 

 

/**
	 * 发起一个post请求,返回string对象
	 * 
	 * @param stringListener
	 * @param isLoadCache
	 *            true 为加载缓存,false为不加载缓存
	 */
	public void postRequest(final String text,
			final RequestStringListener stringListener) {
		if (!isNetworkConnect()) {
			whetherOpenNet();
			return;
		}
		showPd(text);
		Runnable task = new Runnable() {

			@Override
			public void run() {
				try {
					final String result = postStringResult();
					if (requestThread.isInterrupted()) {
						showLog("is interrupted");
						return;
					}
					if (result == null) {
						netError();
						return;
					}
					post(new Complete() {

						@Override
						public void run() {
							super.run();
							stringListener.onComplete(result);
							sendEmptyMessage(REQUEST_SUCCESS);
						}
					});
				} catch (SocketTimeoutException e) {
					timeOut(text, stringListener);
					e.printStackTrace();
				} catch (Exception e) {
					netError();
					e.printStackTrace();
				}

			}
		};
		requestThread = new Thread(task);
		requestThread.start();
	}

	/**
	 * 网络连接超时
	 * 
	 * @param text
	 * @param stringListener
	 */
	protected void timeOut(final String text,
			final RequestStringListener stringListener) {
		sendEmptyMessage(REQUEST_TIMEOUT);
		Looper.prepare();
		post(new Complete() {

			@Override
			public void run() {
				super.run();
				new AlertDialog.Builder(activity)
						.setTitle("网络连接超时")
						.setNegativeButton("取消", null)
						.setPositiveButton("重连",
								new DialogInterface.OnClickListener() {

									@Override
									public void onClick(DialogInterface dialog,
											int which) {
										showLog("重连");
										postRequest(text, stringListener);
									}
								}).show();
			}
		});

	}

	/**
	 * 网络连接错误或返回数据为空
	 * 
	 */
	protected void netError() {
		sendEmptyMessage(REQUEST_ERROR);
		Looper.prepare();
		post(new Complete() {

			@Override
			public void run() {
				super.run();
				if (!isNetworkConnect()) {
					whetherOpenNet();
				} else {
					Toast.makeText(getActivity(), "网络连接失败,请稍后重试",
							Toast.LENGTH_LONG).show();
				}
			}
		});
	}

三.使用

 

 

封装完成后就可以使用了.

 

NetApi netApi = new NetApi(MainActivity.this,
				"http://192.168.10.233:8089/web_test/json");
		netApi.addParams("test", "test");
		netApi.postRequest("测试请求", new RequestStringListener() {

			@Override
			public void onComplete(String result) {
				Log.d("test", "result is --->" + result);
			}
		});

 

四.贴出完整代码

package com.example.test_android;

import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.SocketTimeoutException;
import java.net.URL;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.Map;

import org.json.JSONException;

import android.app.Activity;
import android.app.AlertDialog;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.DialogInterface.OnCancelListener;
import android.content.Intent;
import android.net.ConnectivityManager;
import android.os.Handler;
import android.os.Looper;
import android.provider.Settings;
import android.util.Log;
import android.widget.Toast;

/**
 * 网络接口,post请求string或者get请求json,里面只包含一个线程,只能同时发送一个网络请求
 * 
 * @author oldfeel
 * 
 */
public class NetApi extends Handler {
	/** 打开网络连接 */
	public static final int OPEN_NETWORK = -1;
	/** 请求成功 */
	public static final int REQUEST_SUCCESS = 1;
	/** 请求失败 */
	public static final int REQUEST_ERROR = 2;
	/** 网络连接超时 */
	public static final int REQUEST_TIMEOUT = 3;
	/** 超时时间限制 */
	private static final int TIME_OUT = 30 * 1000;
	private Activity activity;
	private Map<String, String> params = new HashMap<String, String>();
	private String path = "";
	private ProgressDialog pd;
	private Thread requestThread;
	private AlertDialog dialog;

	/**
	 * 构造一个netapi对象
	 * 
	 * @param context
	 * 
	 * @param path
	 *            这次请求需要调用的url
	 */
	public NetApi(Activity activity, String path) {
		this.activity = activity;
		this.path = path;
	}

	/**
	 * 添加参数,用url编码格式
	 * 
	 * @param key
	 * @param value
	 */
	public void addParams(String key, Object value) {
		if (!isEmpty(key) && !isEmpty(value)) {
			params.put(key.trim(), value.toString().trim());// *.trim(),取消首尾空格
		}
	}

	/**
	 * 补充路径,比如添加 /信息类别id/新闻id
	 * 
	 * @param objects
	 */
	public void addPath(Object... objects) {
		for (Object object : objects) {
			path = path + "/" + getUrlEncode(object);
		}
	}

	/**
	 * 检查该参数是否有内容,没有的话就不用添加了
	 * 
	 * @param str
	 * @return true为没有内容,false为有内容
	 */
	public boolean isEmpty(Object str) {
		if (str == null || str.toString().length() == 0)
			return true;
		else
			return false;
	}

	/**
	 * 获取url编码的字符串
	 * 
	 * @param value
	 * @return
	 */
	private String getUrlEncode(Object value) {
		try {
			return URLEncoder.encode(value.toString().trim(), "utf-8");
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}
		return null;
	}

	/**
	 * get请求,拼接url路径,并对参数进行urlencode
	 */
	public String getPath() {
		if (params.size() == 0) {
			return path;
		}
		StringBuilder sb = new StringBuilder();
		boolean first = path.indexOf("?") == -1; // 不包含?(first=true)说明是第一次添加参数,包含?说明url中带有参数
		for (String key : params.keySet()) {
			if (first) {
				first = false;
				sb.append("?");
			} else {
				sb.append("&");
			}
			sb.append(key + "=" + getUrlEncode(params.get(key)));
		}
		return path + sb.toString();
	}

	/**
	 * post请求,传入的参数
	 * 
	 * @return
	 */
	private String postParams() {
		if (params.size() == 0) {
			return path;
		}
		boolean isFrist = true;
		StringBuilder sb = new StringBuilder();
		for (String key : params.keySet()) {
			if (isFrist) {
				sb.append(key + "=" + params.get(key));
				isFrist = false;
			} else {
				sb.append("&" + key + "=" + params.get(key));
			}
		}
		return sb.toString();
	}

	/**
	 * 显示进度条提示
	 * 
	 * @param message
	 */
	private void showPd(String message) {
		showLog("start connect");
		if (message == null || message.length() == 0) {
			return;
		}
		if (pd != null) {
			pd.cancel();
			pd = null;
		}
		pd = new ProgressDialog(activity);
		pd.setMessage(message);
		pd.setOnCancelListener(new OnCancelListener() {

			@Override
			public void onCancel(DialogInterface dialog) {
				requestThread.interrupt();
			}
		});
		pd.setCancelable(true);
		pd.show();
	}

	/**
	 * 发起一个post请求,返回string对象
	 * 
	 * @param stringListener
	 * @param isLoadCache
	 *            true 为加载缓存,false为不加载缓存
	 */
	public void postRequest(final String text,
			final RequestStringListener stringListener) {
		if (!isNetworkConnect()) {
			whetherOpenNet();
			return;
		}
		showPd(text);
		Runnable task = new Runnable() {

			@Override
			public void run() {
				try {
					final String result = postStringResult();
					if (requestThread.isInterrupted()) {
						showLog("is interrupted");
						return;
					}
					if (result == null) {
						netError();
						return;
					}
					post(new Complete() {

						@Override
						public void run() {
							super.run();
							stringListener.onComplete(result);
							sendEmptyMessage(REQUEST_SUCCESS);
						}
					});
				} catch (SocketTimeoutException e) {
					timeOut(text, stringListener);
					e.printStackTrace();
				} catch (Exception e) {
					netError();
					e.printStackTrace();
				}

			}
		};
		requestThread = new Thread(task);
		requestThread.start();
	}

	/**
	 * 网络连接超时
	 * 
	 * @param text
	 * @param stringListener
	 */
	protected void timeOut(final String text,
			final RequestStringListener stringListener) {
		sendEmptyMessage(REQUEST_TIMEOUT);
		Looper.prepare();
		post(new Complete() {

			@Override
			public void run() {
				super.run();
				new AlertDialog.Builder(activity)
						.setTitle("网络连接超时")
						.setNegativeButton("取消", null)
						.setPositiveButton("重连",
								new DialogInterface.OnClickListener() {

									@Override
									public void onClick(DialogInterface dialog,
											int which) {
										showLog("重连");
										postRequest(text, stringListener);
									}
								}).show();
			}
		});

	}

	/**
	 * 网络连接错误或返回数据为空
	 * 
	 */
	protected void netError() {
		sendEmptyMessage(REQUEST_ERROR);
		Looper.prepare();
		post(new Complete() {

			@Override
			public void run() {
				super.run();
				if (!isNetworkConnect()) {
					whetherOpenNet();
				} else {
					Toast.makeText(getActivity(), "网络连接失败,请稍后重试",
							Toast.LENGTH_LONG).show();
				}
			}
		});
	}

	/**
	 * 发送post上传文件,获取字符串结果
	 * 
	 * @param isLoadCache
	 *            true为加载缓存,false为不加载缓存
	 */
	public String postStringResult() throws IOException, JSONException {
		showLog("path is " + path);
		showLog("post is " + postParams());
		HttpURLConnection conn = getConn(path, "POST");
		// 配置post请求的参数
		DataOutputStream outputStream = new DataOutputStream(
				conn.getOutputStream());
		outputStream.writeBytes(postParams());
		outputStream.flush();
		outputStream.close();

		if (conn.getResponseCode() == HttpURLConnection.HTTP_OK) {
			String data = formatStreamToString(conn);
			showLog("result is " + data);
			return data;
		}
		return null;
	}

	/**
	 * 根据url获取网络链接
	 * 
	 * @param path
	 * @param requestType
	 *            请求方式,post或者get
	 * @return
	 * @throws IOException
	 */
	private HttpURLConnection getConn(String path, String requestType)
			throws IOException {
		URL url = new URL(path);
		HttpURLConnection conn = (HttpURLConnection) url.openConnection();
		conn.setDoOutput(true);
		conn.setDoInput(true);
		conn.setRequestMethod(requestType);
		conn.setConnectTimeout(TIME_OUT);
		conn.setReadTimeout(TIME_OUT);
		conn.connect();
		return conn;
	}

	/**
	 * 将网络连接中的输入流转换成string字符串
	 * 
	 * @param conn
	 * @return
	 * @throws IOException
	 */
	private String formatStreamToString(HttpURLConnection conn)
			throws IOException {
		StringBuffer out = new StringBuffer();
		BufferedReader input = new BufferedReader(new InputStreamReader(
				conn.getInputStream()));
		String line = null;
		while ((line = input.readLine()) != null) {
			out.append(line);
		}
		input.close();
		return out.toString();
	}

	class Complete implements Runnable {
		@Override
		public void run() {
			if (pd != null) {
				pd.cancel();
			}
			requestThread.interrupt();
		}
	}

	/**
	 * 判断网络连接
	 */
	private boolean isNetworkConnect() {
		ConnectivityManager cm = (ConnectivityManager) activity
				.getSystemService(Context.CONNECTIVITY_SERVICE);
		cm.getActiveNetworkInfo();
		if (cm.getActiveNetworkInfo() != null) {
			return cm.getActiveNetworkInfo().isAvailable();
		}
		return false;
	}

	/**
	 * 打开网络对话框
	 */
	private void whetherOpenNet() {
		if (dialog != null) {
			dialog.cancel();
			dialog = null;
		}
		AlertDialog.Builder builder = new AlertDialog.Builder(activity);
		builder.setTitle("网络木有连接");
		builder.setMessage("是否打开网络连接");
		builder.setPositiveButton("确定", new DialogInterface.OnClickListener() {

			@Override
			public void onClick(DialogInterface dialog, int which) {
				activity.startActivityForResult(new Intent(
						Settings.ACTION_WIRELESS_SETTINGS), OPEN_NETWORK);
			}
		});
		builder.setNegativeButton("取消", null);
		dialog = builder.create();
		dialog.show();
	}

	/**
	 * 打印日志
	 * 
	 * @param log
	 */
	private void showLog(String log) {
		Log.d("example", log);
	}

	/**
	 * 获取当前NetApi绑定的activity
	 * 
	 * @return
	 */
	public Activity getActivity() {
		return this.activity;
	}

	/**
	 * 请求string的监听
	 */
	public interface RequestStringListener {
		/** 返回字符串 */
		public void onComplete(String result);
	}
}
posted @ 2013-10-28 10:10  oldfeel  阅读(694)  评论(0编辑  收藏  举报