Android使用http协议与服务器通信
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可以合并
更多相关文章
- Log分析
- Android(安卓)计时器Timer用法
- Android的消息机制
- 解决Only the original thread that created a view hierarchy c
- GalHttprequest类库简介——android平台上的一个轻量级的http网
- Android(安卓)网络访问框架 NiceDay 发布
- Java事件模型与Android事件模型的比较
- Android之Handle全面理解
- Android(安卓)Binder机制(一) Binder的设计和框架