Android使用http协议与服务器通信

网上介绍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

packagecom.handspeaker.network;importjava.io.IOException;importjava.io.UnsupportedEncodingException;importjava.net.URI;importjava.net.URISyntaxException;importjava.util.concurrent.ExecutorService;importjava.util.concurrent.Executors;importorg.apache.http.HttpResponse;importorg.apache.http.client.ClientProtocolException;importorg.apache.http.client.HttpClient;importorg.apache.http.client.methods.HttpPost;importorg.apache.http.entity.StringEntity;importorg.apache.http.impl.client.DefaultHttpClient;importorg.apache.http.params.HttpConnectionParams;importorg.apache.http.params.HttpParams;importorg.apache.http.protocol.HTTP;importorg.apache.http.util.EntityUtils;importorg.json.JSONObject;importandroid.app.Activity;importandroid.content.Context;importandroid.net.ConnectivityManager;importandroid.os.Handler;importandroid.util.Log;/****用于封装&简化http通信**/publicclassPostRequestimplementsRunnable{privatestaticfinalintNO_SERVER_ERROR=1000;//服务器地址publicstaticfinalStringURL="fillyourownurl";//一些请求类型publicfinalstaticStringADD="/add";publicfinalstaticStringUPDATE="/update";publicfinalstaticStringPING="/ping";//一些参数privatestaticintconnectionTimeout=60000;privatestaticintsocketTimeout=60000;//类静态变量privatestaticHttpClienthttpClient=newDefaultHttpClient();privatestaticExecutorServiceexecutorService=Executors.newCachedThreadPool();privatestaticHandlerhandler=newHandler();//变量privateStringstrResult;privateHttpPosthttpPost;privateHttpResponsehttpResponse;privateOnReceiveDataListeneronReceiveDataListener;privateintstatusCode;/***构造函数,初始化一些可以重复使用的变量*/publicPostRequest(){strResult=null;httpResponse=null;httpPost=newHttpPost();}/***注册接收数据监听器*@paramlistener*/publicvoidsetOnReceiveDataListener(OnReceiveDataListenerlistener){onReceiveDataListener=listener;}/***根据不同的请求类型来初始化httppost**@paramrequestType*请求类型*@paramnameValuePairs*需要传递的参数*/publicvoidiniRequest(StringrequestType,JSONObjectjsonObject){httpPost.addHeader("Content-Type","text/json");httpPost.addHeader("charset","UTF-8");httpPost.addHeader("Cache-Control","no-cache");HttpParamshttpParameters=httpPost.getParams();HttpConnectionParams.setConnectionTimeout(httpParameters,connectionTimeout);HttpConnectionParams.setSoTimeout(httpParameters,socketTimeout);httpPost.setParams(httpParameters);try{httpPost.setURI(newURI(URL+requestType));httpPost.setEntity(newStringEntity(jsonObject.toString(),HTTP.UTF_8));}catch(URISyntaxExceptione1){e1.printStackTrace();}catch(UnsupportedEncodingExceptione){e.printStackTrace();}}/***新开一个线程发送http请求*/publicvoidexecute(){executorService.execute(this);}/***检测网络状况**@returntrueisavailableelsefalse*/publicstaticbooleancheckNetState(Activityactivity){ConnectivityManagerconnManager=(ConnectivityManager)activity.getSystemService(Context.CONNECTIVITY_SERVICE);if(connManager.getActiveNetworkInfo()!=null){returnconnManager.getActiveNetworkInfo().isAvailable();}returnfalse;}/***发送http请求的具体执行代码*/@Overridepublicvoidrun(){httpResponse=null;try{httpResponse=httpClient.execute(httpPost);strResult=EntityUtils.toString(httpResponse.getEntity());}catch(ClientProtocolExceptione1){strResult=null;e1.printStackTrace();}catch(IOExceptione1){strResult=null;e1.printStackTrace();}finally{if(httpResponse!=null){statusCode=httpResponse.getStatusLine().getStatusCode();}else{statusCode=NO_SERVER_ERROR;}if(onReceiveDataListener!=null){//将注册的监听器的onReceiveData方法加入到消息队列中去执行handler.post(newRunnable(){@Overridepublicvoidrun(){onReceiveDataListener.onReceiveData(strResult,statusCode);}});}}}/***用于接收并处理http请求结果的监听器**/publicinterfaceOnReceiveDataListener{/***thecallbackfunctionforreceivingtheresultdata*frompostrequest,andfurtherprocessingwillbedonehere*@paramstrResulttheresultinstringstyle.*@paramStatusCodethestatusofthepost*/publicabstractvoidonReceiveData(StringstrResult,intStatusCode);}}

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

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

2.注册监听器

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

4.调用PostRequest的execute方法

可能的改进:

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

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


更多相关文章

  1. Log分析
  2. Android(安卓)计时器Timer用法
  3. Android的消息机制
  4. 解决Only the original thread that created a view hierarchy c
  5. GalHttprequest类库简介——android平台上的一个轻量级的http网
  6. Android(安卓)网络访问框架 NiceDay 发布
  7. Java事件模型与Android事件模型的比较
  8. Android之Handle全面理解
  9. Android(安卓)Binder机制(一) Binder的设计和框架

随机推荐

  1. 带你了解Android接口回调机制
  2. Android让页面默认弹出输入法的问题
  3. android 启动页和如何判断app是否第一次
  4. 《Android外部存储》
  5. android 系统签名
  6. Android(安卓)ComboBox
  7. Android 最简单的二维码和条形码扫描生成
  8. Android studio 安卓炫酷动画整合
  9. Android底部导航栏之RadioButton
  10. Context都没弄明白,还怎么做Android开发?