編輯:關於Android編程
一、前言
最近學習http框架。
目前寫的這個框架暫時只適用於學習之用,實際用於項目之中還需要不斷的優化。
要從服務器或者網絡獲取數據,顯示到UI上面,網絡請求的操作不能放在UI線程中進行,android為我們封裝了AsyncTask類來進行異步的請求操作,所以這個Http框架基於AsyncTask。
二、框架主要類
定義Request類,定義url,服務器返回數據,post的請求params,下載進度等參數。
定義HttpUtil類來封裝http請求代碼。在裡面定義execute()方法,該方法判斷是get還是post,然後再去call get(),post() 方法。post() 請求需要的參數在Request中設置.
在AsyncTask中,doingBackground()方法中 execute http,將返回的數據寫到內存中變成String返回,如果數據較大,可以先存到文件中,把path返回,在不同的callback中處理。
三、框架搭建
1. 首先,我們建立 HttpClientUtil.java 類,用於處理HTTP的get和post,裡面定義execute()方法,該方法判斷是get還是post,然後再去call get(),post() 方法,post() 請求需要的參數在Request中設置.:
/**
* @author Mr.傅
*/
public class HttpClientUtil {
/**
* 執行HTTP方法,Request 設置請求類型
* @param request
* @return
* @throws Exception
*/
public static HttpResponse excute(Request request) throws Exception{
switch (request.requestMethod) {
case GET:
return get(request);
case POST:
return post(request);
default:
//這裡沒有定義 DELETE 和 PUT 操作
throw new IllegalStateException("you doesn't define this requestmethod");
}
}
private static HttpResponse get(Request request) throws Exception {
HttpClient client = new DefaultHttpClient();
HttpGet get = new HttpGet(request.url);
addHeader(get, request.headers);
//返回的結果放到上一層進行處理
HttpResponse response = client.execute(get);
return response;
}
private static HttpResponse post(Request request) throws Exception {
HttpClient client = new DefaultHttpClient();
HttpPost post = new HttpPost(request.url);
addHeader(post, request.headers);
//post的請求參數在 Request 中定義,如果為空,則沒有定義
if (request.entity == null) {
throw new IllegalStateException("you forget to set post content to the httpost");
}else {
post.setEntity(request.entity);
}
HttpResponse response = client.execute(post);
return response;
}
/**
* 請求頭
* @param request
* @param headers
*/
public static void addHeader(HttpUriRequest request, Map headers){
if (headers != null && headers.size() > 0 ) {
for(Entry entry : headers.entrySet()){
request.addHeader(entry.getKey(), entry.getValue());
}
}
}
}
2. 上述代碼中的 Request.java 類,定義url,服務器返回數據,post的請求params,下載進度等參數定義如下:/**
* @author Mr.傅
*/
public class Request {
public enum RequestMethod{
GET,POST,DELETE,PUT
}
RequestMethod requestMethod;
public String url;
/**
* Http請求參數的類型,包括表單,string, byte等
*/
public HttpEntity entity;
public Map headers;
public static final String ENCODING = "UTF-8";
/**
* 設置回調接口,該接口中的onSuccess和onFilure方法需要在體現在UI線程當中
*/
public ICallback callback;
private RequestTask task;
public Request(String url, RequestMethod method) {
this.url = url;
this.requestMethod = method;
}
public void setEntity(ArrayList forms){
try {
entity = new UrlEncodedFormEntity(forms, ENCODING);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}
public void setEntity(String postContent){
try {
entity = new StringEntity(postContent, ENCODING);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}
public void setEntity(byte[] bytes){
entity = new ByteArrayEntity(bytes);
}
/**
* 設置回調方法,在ui線程中定義需要請求 返回的 方法
* @param callback
*/
public void setCallback(ICallback callback) {
this.callback = callback;
}
/**
* UI線程中,執行該方法,開啟一個AsyncTask,注意AsyncTask每次使用必須重新new
*/
public void execute() {
task = new RequestTask(this);
task.execute();
}
}
3. ICallback接口,該接口的onFilure和onSuccess方法在UI線程當中實現,如果在RequestTask中doInBackground中HttpResponse返回成功則在onPostExecute中調用onSuccess,否則調用onFilure,並傳遞已經解析了的返回參數:public interface ICallback {
void onFilure(Exception result);
void onSuccess(Object result);
/**
* 將從服務器得到的HttpResponse進行解析,解析完成以後,返回給UI線程
*/
Object handle(HttpResponse response);
}
4. RequestTask 繼承自 AsyncTask ,在doInBackground 進行HTTP請求,同時對HTTP請求返回的數據結果進行解析,通過調用callback中的handle方法,解析HTTP請求返回的參數,返回後的結果(如果拋出異常,將異常也返回),在onPostExecute中進行處理,調用不同的方法,返回到UI線程,代碼如下:
/** * @author Mr.傅 * @version create time:2014年5月17日 下午2:19:39 */ public class RequestTask extends AsyncTask5. AbstractCallback.java 該類 中實現接口 ICallback 的 handle 方法,該方法主要作用是,對HTTP返回的HttpResponse 進行解析,如果返回狀態碼是200,則進行下一步處理;如果UI調用了setPath()方法,設置了保存的路徑的話,就將HTTP返回的數據先寫入到文件中,然後文件中讀取出來,放入到對應的解析實現類中,如:StringCallback,JsonCallback等, 返回到doInBackground 中(doInBackground 中的return request.callback.handle(response)步驟)。如果沒有設置路徑,則直接調用bindData(EntityUtils.toString(entity)),
/**
* @author Mr.傅
*/
public abstract class AbstractCallback implements ICallback{
/**
* 文件存放的路徑
*/
public String path;
private static final int IO_BUFFER_SIZE = 4*1024;
@Override
public Object handle(HttpResponse response){
// file, json, xml, image, string
int statusCode = -1;
InputStream in = null;
try {
HttpEntity entity = response.getEntity();
statusCode = response.getStatusLine().getStatusCode();
switch (statusCode) {
case HttpStatus.SC_OK:
if (TextUtil.isValidate(path)) {
//將服務器返回的數據寫入到文件當中
FileOutputStream fos = new FileOutputStream(path);
if (entity.getContentEncoding() != null) {
String encoding = entity.getContentEncoding().getValue();
if (encoding != null && "gzip".equalsIgnoreCase(encoding)) {
in = new GZIPInputStream(entity.getContent());
} if (encoding != null && "deflate".equalsIgnoreCase(encoding)) {
in = new InflaterInputStream(entity.getContent());
}
} else {
in = entity.getContent();
}
byte[] b = new byte[IO_BUFFER_SIZE];
int read;
while ((read = in.read(b)) != -1) {
// TODO update progress
fos.write(b, 0, read);
}
fos.flush();
fos.close();
in.close();
//寫入文件之後,再從文件當中將數據讀取出來,直接返回對象
return bindData(path);
} else {
// 需要返回的是對象,而不是數據流,所以需要去解析服務器返回的數據
// 對應StringCallback 中的return content;
//2. 調用binData
return bindData(EntityUtils.toString(entity));
}
default:
break;
}
return null;
} catch (ParseException e) {
//這些異常處理都沒有進行操作,後面的文章會再做處理
} catch (IOException e) {
}
return null;
}
/**
* 數據放入到不同的Callback中處理
*/
protected Object bindData(String content){
//StringCallback等方法中實現了該方法
return null;
}
/**
* 如果要存入到文件,則設置文件路徑
*/
public AbstractCallback setPath(String path){
this.path = path;
return this;
}
}
6. StringCallback.java 目前的代碼,只實現了該callback,JsonCallback,PathCallback,會在後面的文章當中具體實現:public abstract class StringCallback extends AbstractCallback {
@Override
protected Object bindData(String content) {
//如果路徑存在,則重新講數據從文件中讀取出來
if (TextUtil.isValidate(path)) {
return IOUtiliteies.readFromFile(path);
}
return content;
}
}
7. 當中用到的TextUtil.java 類 public class TextUtil {
public static boolean isValidate(String content){
return content != null && !"".equals(content.trim());
}
public static boolean isValidate(ArrayList content){
return content != null && content.size() > 0;
}
} 8. UI線程中具體調用方法如下:private void requestString() {
//設置保存路徑
String path = Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator + "mrfu_http.txt";
Request request = new Request("http://www.baidu.com", RequestMethod.GET);
request.setCallback(new StringCallback() {
@Override
public void onSuccess(Object result) {
mTestResultLabel.setText((String)result);
}
@Override
public void onFilure(Exception result) {
result.printStackTrace();
}
}.setPath(path));
request.execute();
}
其中mTestResultLabel 是TextView
可以看到實現效果,這裡我們在SD卡的根目錄下將返回結果存入到了 "mrfu_http.txt" 文件中,同時顯示到了 UI 上面:如圖所示:
源碼下載:http://download.csdn.net/detail/fu222cs98/7377683
Android使用adb命令往模擬器裡安裝軟件
我將模擬器解壓到C:\android-sdk-windows\在C:\android-sdk-windows\platform-tools這個文件夾裡有個a
Android項目實戰手把手教你畫圓形水波紋loadingview
本文實例講解的是如何畫一個滿滿圓形水波紋loadingview,這類效果應用場景很多,比如內存占用百分比之類的,分享給大家供大家參考,具體內容如下效果圖如下:預備的知識:
Android微信支付和支付寶支付服務端操作放到客戶端
前言現在的APP大部分需要接入支付功能,而支付的主流就是微信支付和支付寶支付,網上關於微信支付和支付支付資料很多,但是這些資料隨著官方的變動可能變得毫無用處,所以我建議直
Activity的創建和顯示以及源碼分析記錄
Tips:此源碼分析基於Android 4.2先來看看一個Activity上的UI控件結構: 圖1-1 Activity中的UI組件結構好了現在開