因为android 4.0 以后的发送网络请求必须要放到异步线程中,而异步线程必须跟handle合作才能更新主线程中的UI,所以建议用一个类继承handler来异步处理网络请求.
首先,每次发送网络请求都需要先检测网络连接是否正常.其次需要向用户提供一个提示信息,比如ProgressDialog,然后简单粗暴的把网络请求结果设为3种:1->请求成功;2->请求失败;3->连接超时.请求成功的话就返回正确的结果,请求失败就提示网络请求失败.请求超时就询问是否重连.所以需要封装的就有:
/** * 判断网络连接 */ 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 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(); } } }); }
封装完成后就可以使用了.
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); } }