网上介绍Android上http通信的文章很多,不过大部分只给出了实现代码的片段,一些注意事项和如何设计一个合理的类用来处理所有的http请求以及返回结果,一般都不会提及。因此,自己对此做了些总结,给出了我的一个解决方案。

首先,需要明确一下http通信流程,Android目前提供两种http通信方式,HttpURLConnection和HttpClient,HttpURLConnection多用于发送或接收流式数据,因此比较适合上传/下载文件,HttpClient相对来讲更大更全能,但是速度相对也要慢一点。在此只介绍HttpClient的通信流程:

1.创建HttpClient对象,改对象可以用来多次发送不同的http请求

2.创建HttpPost或HttpGet对象,设置参数,每发送一次http请求,都需要这样一个对象

3.利用HttpClient的execute方法发送请求并等待结果,该方法会一直阻塞当前线程,直到返回结果或抛出异常。

4.针对结果和异常做相应处理

根据上述流程,发现在设计类的时候,有几点需要考虑到:

1.HttpClient对象可以重复使用,因此可以作为类的静态变量

2.HttpPost/HttpGet对象一般无法重复使用(如果你每次请求的参数都差不多,也可以重复使用),因此可以创建一个方法用来初始化,同时设置一些需要上传到服务器的资源

3.目前Android不再支持在UI线程中发起Http请求,实际上也不该这么做,因为这样会阻塞UI线程。因此还需要一个子线程,用来发起Http请求,即执行execute方法

4.不同的请求对应不同的返回结果,对于如何处理返回结果(一般来说都是解析json&更新UI),需要有一定的自由度。

5.最简单的方法是,每次需要发送http请求时,开一个子线程用于发送请求,子线程中接收到结果或抛出异常时,根据情况给UI线程发送message,最后在UI线程的handler的handleMessage方法中做结果解析和UI更新。这么写虽然简单,但是UI线程和Http请求的耦合度很高,而且代码比较散乱、丑陋。

基于上述几点原因,我设计了一个PostRequest类,用于满足我的http通信需求。我只用到了Post请求,如果你需要Get请求,也可以改写成GetRequest

package com.handspeaker.network;import java.io.IOException;import java.io.UnsupportedEncodingException;import java.net.URI;import java.net.URISyntaxException;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;import org.apache.http.HttpResponse;import org.apache.http.client.ClientProtocolException;import org.apache.http.client.HttpClient;import org.apache.http.client.methods.HttpPost;import org.apache.http.entity.StringEntity;import org.apache.http.impl.client.DefaultHttpClient;import org.apache.http.params.HttpConnectionParams;import org.apache.http.params.HttpParams;import org.apache.http.protocol.HTTP;import org.apache.http.util.EntityUtils;import org.json.JSONObject;import android.app.Activity;import android.content.Context;import android.net.ConnectivityManager;import android.os.Handler;import android.util.Log;/** *  * 用于封装&简化http通信 *  */public class PostRequest implements Runnable {        private static final int NO_SERVER_ERROR=1000;    //服务器地址    public static final String URL = "fill your own url";    //一些请求类型    public final static String ADD = "/add";    public final static String UPDATE = "/update";    public final static String PING = "/ping";    //一些参数    private static int connectionTimeout = 60000;    private static int socketTimeout = 60000;    //类静态变量    private static HttpClient httpClient=new DefaultHttpClient();    private static ExecutorService executorService=Executors.newCachedThreadPool();    private static Handler handler = new Handler();    //变量    private String strResult;    private HttpPost httpPost;    private HttpResponse httpResponse;    private OnReceiveDataListener onReceiveDataListener;    private int statusCode;    /**     * 构造函数,初始化一些可以重复使用的变量     */    public PostRequest() {        strResult = null;        httpResponse = null;        httpPost = new HttpPost();    }        /**     * 注册接收数据监听器     * @param listener     */    public void setOnReceiveDataListener(OnReceiveDataListener listener) {        onReceiveDataListener = listener;    }    /**     * 根据不同的请求类型来初始化httppost     *      * @param requestType     *            请求类型     * @param nameValuePairs     *            需要传递的参数     */    public void iniRequest(String requestType, JSONObject jsonObject) {        httpPost.addHeader("Content-Type", "text/json");        httpPost.addHeader("charset", "UTF-8");        httpPost.addHeader("Cache-Control", "no-cache");        HttpParams httpParameters = httpPost.getParams();        HttpConnectionParams.setConnectionTimeout(httpParameters,                connectionTimeout);        HttpConnectionParams.setSoTimeout(httpParameters, socketTimeout);        httpPost.setParams(httpParameters);        try {            httpPost.setURI(new URI(URL + requestType));            httpPost.setEntity(new StringEntity(jsonObject.toString(),                    HTTP.UTF_8));        } catch (URISyntaxException e1) {            e1.printStackTrace();        } catch (UnsupportedEncodingException e) {            e.printStackTrace();        }    }    /**     * 新开一个线程发送http请求     */    public void execute() {        executorService.execute(this);    }    /**     * 检测网络状况     *      * @return true is available else false     */    public static boolean checkNetState(Activity activity) {        ConnectivityManager connManager = (ConnectivityManager) activity                .getSystemService(Context.CONNECTIVITY_SERVICE);        if (connManager.getActiveNetworkInfo() != null) {            return connManager.getActiveNetworkInfo().isAvailable();        }        return false;    }    /**     * 发送http请求的具体执行代码     */    @Override    public void run() {        httpResponse = null;        try {            httpResponse = httpClient.execute(httpPost);            strResult = EntityUtils.toString(httpResponse.getEntity());        } catch (ClientProtocolException e1) {            strResult = null;            e1.printStackTrace();        } catch (IOException e1) {            strResult = null;            e1.printStackTrace();        } finally {            if (httpResponse != null) {                statusCode = httpResponse.getStatusLine().getStatusCode();            }            else            {                statusCode=NO_SERVER_ERROR;            }            if(onReceiveDataListener!=null)            {                //将注册的监听器的onReceiveData方法加入到消息队列中去执行                handler.post(new Runnable() {                    @Override                    public void run() {                        onReceiveDataListener.onReceiveData(strResult, statusCode);                    }                });            }        }    }    /**     * 用于接收并处理http请求结果的监听器     *     */    public interface OnReceiveDataListener {        /**         * the callback function for receiving the result data         * from post request, and further processing will be done here         * @param strResult the result in string style.         * @param StatusCode the status of the post         */        public abstract void onReceiveData(String strResult,int StatusCode);    }}

代码使用了观察者模式,任何需要接收http请求结果的类,都要实现OnReceiveDataListener接口的抽象方法,同时PostRequest实例调用setOnReceiveDataListener方法,注册该监听器。完整调用步骤如下:

1.创建PostRequest对象,实现onReceiveData接口,编写自己的onReceiveData方法

2.注册监听器

3.调用PostRequest的iniRequest方法,初始化本次request

4.调用PostRequest的execute方法

可能的改进:

1.如果需要多个观察者,可以把只能注册单个监听器改为可以注册多个监听器,维护一个监听器List。

2.如果需求比较简单,并希望调用流程更简洁,iniRequest和execute可以合并

如果有更好的方法或者问题,欢迎随时交流

更多相关文章

  1. Android的两种数据存储方式分析(二)
  2. android 异步获取图片
  3. 实战技巧:Android异步指南
  4. [译] 在 Android(安卓)使用协程(part III) - 在实际工作中使用
  5. Android面试系列文章2018之Android部分HandlerThread机制篇
  6. [Android]Thread线程入门3--多线程
  7. android - 为响应度而设计 - 开发文档翻译
  8. Android(安卓)Handler
  9. android静默安装的实现

随机推荐

  1. Android(安卓)实现轮播图效果(三) 底部圆点
  2. Android(安卓)后台定时任务的实现和改进
  3. android系统 在jack-server下 生成 jar
  4. Android(安卓)retrofit网络交互在后台返
  5. Android简易计算器(四)—— 完整逻辑代码
  6. iOS开发-UITableView常用方法
  7. Android实现 广告识别之 广告库
  8. Android(安卓)P Vold分析 VolumeBase::cr
  9. android应用程序监听SMS Intent广播
  10. Android(安卓)ConstraintLayout 约束布局