Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> Android開發實例 >> 實戰Android仿人人客戶端之網絡模塊處理的架構

實戰Android仿人人客戶端之網絡模塊處理的架構

編輯:Android開發實例

上一篇聊到了通過WebView組件加載人人的訪問授權頁面,接下來就是當用戶輸入人人訪問賬號和密碼,點擊“登錄”按鈕,成功後人人的服務器端會返回AccessToken的值。初次使用,我們本地是沒有存儲session Key的,我們需要通過AccessToken去服務器端請求數據,獲得session Key、sessionSecret和用戶的userId。存儲當前獲得的sessionKey, sessionSecret以備後用。這裡就需要用到網絡這塊的知識,這一篇就來說下仿人人的網絡模塊是如何架構的,先來看下網絡處理模塊的類圖:

 

  一、網絡請求基類(AsyncBaseRequest),是一個實現Runnable接口的線程類。

  初始化時的參數列表:

  1. public AsyncBaseRequest(String url, Map<String, String> parameter, ParseCallback handler, ResultCallback requestCallback) {} 

 參數列表解釋: 

        第一個參數:網絡請求URL;

        第二個參數:網絡請求的參數;

        第三個參數:網絡請求返回數據的解析器;

       第四個參數:網絡請求返回的結果回調接口;
  網絡請求具體實現抽象方法:

  1. protected abstract InputStream getRequestResult() throws IOException; 

  線程核心run()方法裡面的實現:

  1. @Override 
  2. public void run() {  
  3.     try {  
  4.         mInStream = getRequestResult();  
  5.         if (mInStream != null) {  
  6.             String result = new String(readInputStream(mInStream));  
  7.             Object obj = parseHandler.parse(result);  
  8.             requestCallback.onSuccess(flag, obj);  
  9.         } else {  
  10.             System.out.println("get InputStream By HttpURLConnection return result is NULL.");  
  11.         }  
  12.     } catch (IOException e) {  
  13.         requestCallback.onFail(flag, Constant.NETWORK_REQUEST_IOEXCEPTION_CODE); // IO異常標識  
  14.         e.printStackTrace();  
  15.     }  
  16. }  

二、通過HTTP協議發送GET請求的具體實現

  1. package com.everyone.android.net;  
  2.  
  3. import java.io.IOException;  
  4. import java.io.InputStream;  
  5. import java.net.HttpURLConnection;  
  6. import java.net.URL;  
  7. import java.net.URLEncoder;  
  8. import java.util.Map;  
  9.  
  10. import org.apache.http.protocol.HTTP;  
  11.  
  12. import com.everyone.android.callback.ParseCallback;  
  13. import com.everyone.android.callback.ResultCallback;  
  14.  
  15. /**  
  16.  * 功能描述:通過HTTP協議發送GET請求  
  17.  * @author android_ls  
  18.  *  
  19.  */ 
  20. public class AsyncHttpGet extends AsyncBaseRequest {  
  21.  
  22.     /**  
  23.      *   
  24.      */ 
  25.     private static final long serialVersionUID = 2L;  
  26.  
  27.     public AsyncHttpGet(String url, Map<String, String> parameter,  
  28.             ParseCallback handler, ResultCallback requestCallback) throws IOException {  
  29.         super(url, parameter, handler, requestCallback);  
  30.     }  
  31.  
  32.     @Override 
  33.     protected InputStream getRequestResult() throws IOException {  
  34.         StringBuilder sb = new StringBuilder(requestUrl);  
  35.         sb.append('?');  
  36.         for(Map.Entry<String, String> entry : parameter.entrySet()){  
  37.             sb.append(entry.getKey()).append('=')  
  38.                 .append(URLEncoder.encode(entry.getValue(), HTTP.UTF_8)).append('&');  
  39.         }  
  40.         sb.deleteCharAt(sb.length()-1);  
  41.           
  42.         URL url = new URL(sb.toString());  
  43.         mHttpURLConn = (HttpURLConnection)url.openConnection();  
  44.         mHttpURLConn.setConnectTimeout(connectTimeout);  
  45.         mHttpURLConn.setRequestMethod("GET");  
  46.         if(mHttpURLConn.getResponseCode()== HttpURLConnection.HTTP_OK){  
  47.             return mHttpURLConn.getInputStream();  
  48.         }  
  49.         return null;  
  50.     }  
  51.       

三、通過HTTP協議發送POST請求的具體實現

  1. package com.everyone.android.net;  
  2.  
  3. import java.io.IOException;  
  4. import java.io.InputStream;  
  5. import java.io.OutputStream;  
  6. import java.net.HttpURLConnection;  
  7. import java.net.URL;  
  8. import java.net.URLEncoder;  
  9. import java.util.Map;  
  10.  
  11. import org.apache.http.protocol.HTTP;  
  12.  
  13. import com.everyone.android.callback.ParseCallback;  
  14. import com.everyone.android.callback.ResultCallback;  
  15.  
  16. /**  
  17.  * 功能描述:通過HTTP協議發送POST請求  
  18.  * @author android_ls  
  19.  *  
  20.  */ 
  21. public class AsyncHttpPost extends AsyncBaseRequest {  
  22.  
  23.     /**  
  24.      *   
  25.      */ 
  26.     private static final long serialVersionUID = 3L;  
  27.  
  28.     public AsyncHttpPost(String url, Map<String, String> parameter,  
  29.             ParseCallback handler, ResultCallback requestCallback) {  
  30.         super(url, parameter, handler, requestCallback);  
  31.     }  
  32.  
  33.     @Override 
  34.     protected InputStream getRequestResult() throws IOException {  
  35.         StringBuilder sb = new StringBuilder();  
  36.         if(parameter!=null && !parameter.isEmpty()){  
  37.             for(Map.Entry<String, String> entry : parameter.entrySet()){  
  38.                 sb.append(entry.getKey()).append('=')  
  39.                     .append(URLEncoder.encode(entry.getValue(), HTTP.UTF_8)).append('&');  
  40.             }  
  41.             sb.deleteCharAt(sb.length()-1);  
  42.         }  
  43.           
  44.         // 得到實體的二進制數據  
  45.         byte[] entitydata = sb.toString().getBytes();  
  46.         URL url = new URL(requestUrl);  
  47.         mHttpURLConn = (HttpURLConnection)url.openConnection();  
  48.         mHttpURLConn.setRequestMethod("POST");  
  49.         mHttpURLConn.setConnectTimeout(5 * 1000);  
  50.         // 如果通過post提交數據,必須設置允許對外輸出數據  
  51.         mHttpURLConn.setDoOutput(true);  
  52.         mHttpURLConn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");  
  53.         mHttpURLConn.setRequestProperty("Content-Length", String.valueOf(entitydata.length));  
  54.         OutputStream outStream = mHttpURLConn.getOutputStream();  
  55.         outStream.write(entitydata);  
  56.         outStream.flush();  
  57.         outStream.close();  
  58.         if(mHttpURLConn.getResponseCode()== HttpURLConnection.HTTP_OK){  
  59.             return mHttpURLConn.getInputStream();  
  60.         }  
  61.         return null;  
  62.     }  
  63.  

四、線程池類

  1. package com.everyone.android.net;  
  2.  
  3. import java.util.concurrent.AbstractExecutorService;  
  4. import java.util.concurrent.ArrayBlockingQueue;  
  5. import java.util.concurrent.ThreadPoolExecutor;  
  6. import java.util.concurrent.TimeUnit;  
  7.  
  8. import android.util.Log;  
  9.  
  10. /**  
  11.  * 功能描述:網絡請求線程池類  
  12.  * @author android_ls  
  13.  */ 
  14. public class DefaultThreadPool {  
  15.     /**  
  16.      * 用於保存等待執行的任務的阻塞隊列。(有序的先進先出阻塞隊列)  
  17.      */ 
  18.     private static ArrayBlockingQueue<Runnable> mBlockingQueue = new ArrayBlockingQueue<Runnable>(15, true);  
  19.  
  20.     /**  
  21.      * 線程池  
  22.      */ 
  23.     private static AbstractExecutorService mThreadPoolExecutor  
  24.                                                         = new ThreadPoolExecutor(5, 7, 10, TimeUnit.SECONDS, mBlockingQueue,   
  25.                                                                 new ThreadPoolExecutor.DiscardOldestPolicy());  
  26.  
  27.     private static DefaultThreadPool instance = null;  
  28.  
  29.     public static DefaultThreadPool getInstance() {  
  30.         if (instance == null) {  
  31.             instance = new DefaultThreadPool();  
  32.         }  
  33.         return instance;  
  34.     }  
  35.  
  36.     /**  
  37.      * 執行任務  
  38.      * @param r  
  39.      */ 
  40.     public void execute(Runnable r) {  
  41.         mThreadPoolExecutor.execute(r);  
  42.     }  
  43.  
  44.     /**  
  45.      * 關閉,並等待任務執行完成,不接受新任務  
  46.      */ 
  47.     public static void shutdown() {  
  48.         if (mThreadPoolExecutor != null) {  
  49.             mThreadPoolExecutor.shutdown();  
  50.             Log.i(DefaultThreadPool.class.getName(), "DefaultThreadPool shutdown");  
  51.         }  
  52.     }  
  53.  
  54.     /**  
  55.      * 關閉,立即關閉,並掛起所有正在執行的線程,不接受新任務  
  56.      */ 
  57.     public static void shutdownRightnow() {  
  58.         if (mThreadPoolExecutor != null) {  
  59.             mThreadPoolExecutor.shutdownNow();  
  60.             try {  
  61.                 // 設置超時極短,強制關閉所有任務  
  62.                 mThreadPoolExecutor.awaitTermination(1, TimeUnit.MICROSECONDS);  
  63.             } catch (InterruptedException e) {  
  64.                 e.printStackTrace();  
  65.             }  
  66.  
  67.             Log.i(DefaultThreadPool.class.getName(), "DefaultThreadPool shutdownRightnow");  
  68.         }  
  69.     }  
  70.  

五、網絡請求返回的數據解析接口

  1. package com.everyone.android.callback;  
  2.  
  3. /**  
  4.  * 功能描述:網絡請求返回的數據解析接口  
  5.  * @author android_ls  
  6.  *  
  7.  */ 
  8. public interface ParseCallback {  
  9.     /**  
  10.      * 對網絡請求返回的數據進行解析  
  11.      * @param str 要解析的字符串,JSON格式或XML  
  12.      * @return 解析的結果  
  13.      */ 
  14.     public Object parse(String str);  

六、網絡請求返回的結果回調接口

  1. package com.everyone.android.callback;  
  2.  
  3. /**  
  4.  * 功能描述:網絡請求返回的結果回調接口  
  5.  * @author android_ls  
  6.  *  
  7.  */ 
  8. public interface ResultCallback {  
  9.     public void onSuccess(Object obj);  
  10.  
  11.     public void onFail(int errorCode);  
  12.  

七、應用中界面(Activity)的基類

  1. package com.everyone.android;  
  2.  
  3. import java.net.HttpURLConnection;  
  4. import java.util.ArrayList;  
  5. import java.util.List;  
  6.  
  7. import android.app.Activity;  
  8. import android.os.Bundle;  
  9. import android.os.Handler;  
  10. import android.widget.Toast;  
  11.  
  12. import com.everyone.android.net.AsyncBaseRequest;  
  13. import com.everyone.android.net.DefaultThreadPool;  
  14.  
  15. /**  
  16.  * 功能描述:應用中界面(Activity)的基類  
  17.  * 對原有的Activity類進行擴展  
  18.  * @author android_ls  
  19.  */ 
  20. public abstract class AppBaseActivity extends Activity {  
  21.  
  22.     /**  
  23.      * 當前activity所持有的所有網絡請求  
  24.      */ 
  25.     protected List<AsyncBaseRequest> mAsyncRequests;  
  26.  
  27.     protected Handler mHandler;  
  28.  
  29.     protected DefaultThreadPool mDefaultThreadPool;  
  30.  
  31.     @Override 
  32.     protected void onCreate(Bundle savedInstanceState) {  
  33.         super.onCreate(savedInstanceState);  
  34.         setContentView(getLayoutId());  
  35.  
  36.         ((EveryoneApplication) this.getApplication()).addActivity(this);  
  37.  
  38.         mHandler = new Handler();  
  39.         mAsyncRequests = new ArrayList<AsyncBaseRequest>();  
  40.         mDefaultThreadPool = DefaultThreadPool.getInstance();  
  41.  
  42.         // 初始化組件  
  43.         setupView();  
  44.         // 初始化數據  
  45.         initializedData();  
  46.     }  
  47.  
  48.     /**  
  49.      * 布局文件ID  
  50.      * @return  
  51.      */ 
  52.     protected abstract int getLayoutId();  
  53.  
  54.     /**  
  55.      * 初始化組件  
  56.      */ 
  57.     protected abstract void setupView();  
  58.  
  59.     /**  
  60.      * 初始化數據  
  61.      */ 
  62.     protected abstract void initializedData();  
  63.  
  64.     @Override 
  65.     protected void onPause() {  
  66.         /**  
  67.          * 在activity銷毀的時候同時設置停止請求,停止線程請求回調  
  68.          */ 
  69.         cancelRequest();  
  70.         super.onPause();  
  71.     }  
  72.  
  73.     private void cancelRequest() {  
  74.         if (mAsyncRequests != null && mAsyncRequests.size() > 0) {  
  75.             for (AsyncBaseRequest request : mAsyncRequests) {  
  76.                 HttpURLConnection conn = request.getRequestConn();  
  77.                 if (conn != null) {  
  78.                     try {  
  79.                         conn.disconnect();  
  80.                         System.out.println("onDestroy disconnect URL: " + conn.getURL());  
  81.                         mAsyncRequests.remove(request);  
  82.                     } catch (UnsupportedOperationException e) {  
  83.                         //do nothing .  
  84.                     }  
  85.                 }  
  86.             }  
  87.         }  
  88.     }  
  89.  
  90.     /**  
  91.      * 顯示Toast形式的提示信息  
  92.      * @param message  
  93.      */ 
  94.     protected void show(String message) {  
  95.         Toast.makeText(getApplicationContext(), message, Toast.LENGTH_LONG).show();  
  96.     }  
  97.  
  98.     @Override 
  99.     protected void onDestroy() {  
  100.         /**  
  101.          * 在activity銷毀的時候同時設置停止請求,停止線程請求回調  
  102.          */ 
  103.         cancelRequest();  
  104.         super.onDestroy();  
  105.     }  

八、測試(繼承自AppBaseActivity的子類),方法的調用

  1. String url = "http://www.baidu.com/";  
  2.               
  3.             Map<String, String> parameter = new HashMap<String, String>();  
  4.             parameter.put("name", "android_ls");  
  5.             parameter.put("age", "23");  
  6.               
  7.             AsyncBaseRequest asyncBaseRequest = new AsyncHttpPost(url, parameter, new ParseCallback(){  
  8.  
  9.                 @Override 
  10.                 public Object parse(String str) {  
  11.                     // TODO Auto-generated method stub  
  12.                     return null;  
  13.                 }  
  14.                   
  15.             },  
  16.             new ResultCallback(){  
  17.  
  18.                 @Override 
  19.                 public void onSuccess(int flag, Object obj) {  
  20.                     // TODO Auto-generated method stub  
  21.                       
  22.                 }  
  23.  
  24.                 @Override 
  25.                 public void onFail(int flag, int errorCode) {  
  26.                     // TODO Auto-generated method stub  
  27.                       
  28.                 }  
  29.                   
  30.             });  
  31.             mDefaultThreadPool.execute(asyncBaseRequest);  
  32.             mAsyncRequests.add(asyncBaseRequest);  

AsyncBaseRequest的完整代碼

  1. package com.everyone.android.net;  
  2.  
  3. import java.io.ByteArrayOutputStream;  
  4. import java.io.IOException;  
  5. import java.io.InputStream;  
  6. import java.io.Serializable;  
  7. import java.net.HttpURLConnection;  
  8. import java.util.Map;  
  9.  
  10. import com.everyone.android.callback.ParseCallback;  
  11. import com.everyone.android.callback.ResultCallback;  
  12. import com.everyone.android.utils.Constant;  
  13. /**  
  14.  * 功能描述:通過HTTP協議發送網絡請求線程類  
  15.  * @author android_ls  
  16.  *  
  17.  */ 
  18. public abstract class AsyncBaseRequest implements Runnable, Serializable {  
  19.     /**  
  20.      *   
  21.      */ 
  22.     private static final long serialVersionUID = 1L;  
  23.  
  24.     /**  
  25.      * 網絡連接超時,默認值為5秒  
  26.      */ 
  27.     protected int connectTimeout = 5 * 1000;  
  28.       
  29.     /**  
  30.      * 網絡數據讀取超時,默認值為5秒  
  31.      */ 
  32.     protected int readTimeout = 5 * 1000;  
  33.  
  34.     protected void setConnectTimeout(int connectTimeout) {  
  35.         this.connectTimeout = connectTimeout;  
  36.     }  
  37.  
  38.     protected void setReadTimeout(int readTimeout) {  
  39.         this.readTimeout = readTimeout;  
  40.     }  
  41.  
  42.     protected String requestUrl;  
  43.     protected Map<String, String> parameter;  
  44.     private ParseCallback parseHandler;  
  45.     private ResultCallback requestCallback;  
  46.  
  47.     protected HttpURLConnection mHttpURLConn;  
  48.     protected InputStream mInStream;  
  49.  
  50.     public AsyncBaseRequest(String url, Map<String, String> parameter,  
  51.             ParseCallback handler, ResultCallback requestCallback) {  
  52.         this.parseHandler = handler;  
  53.         this.requestUrl = url;  
  54.         this.parameter = parameter;  
  55.         this.requestCallback = requestCallback;  
  56.     }  
  57.  
  58.     /**  
  59.      * 發送網絡請求  
  60.      *   
  61.      * @return 網絡請求返回的InputStream數據流  
  62.      * @throws IOException  
  63.      */ 
  64.     protected abstract InputStream getRequestResult() throws IOException;  
  65.  
  66.     @Override 
  67.     public void run() {  
  68.         try {  
  69.             mInStream = getRequestResult();  
  70.             if (mInStream != null) {  
  71.                 String result = new String(readInputStream(mInStream));  
  72.                 Object obj = parseHandler.parse(result);  
  73.                 requestCallback.onSuccess(obj);  
  74.             } else {  
  75.                 System.out.println("get InputStream By HttpURLConnection return result is NULL.");  
  76.             }  
  77.         } catch (IOException e) {  
  78.             requestCallback.onFail(Constant.NETWORK_REQUEST_IOEXCEPTION_CODE); // IO異常標識  
  79.             e.printStackTrace();  
  80.         }  
  81.     }  
  82.  
  83.     /**  
  84.      * 從輸入流讀取數據  
  85.      *   
  86.      * @param inStream  
  87.      * @return  
  88.      * @throws IOException  
  89.      * @throws Exception  
  90.      */ 
  91.     protected byte[] readInputStream(InputStream inStream) throws IOException {  
  92.         ByteArrayOutputStream outSteam = new ByteArrayOutputStream();  
  93.         byte[] buffer = new byte[1024];  
  94.         int len = 0;  
  95.         while ((len = inStream.read(buffer)) != -1) {  
  96.             outSteam.write(buffer, 0, len);  
  97.         }  
  98.         outSteam.close();  
  99.         inStream.close();  
  100.         return outSteam.toByteArray();  
  101.     }  
  102.  
  103.     public HttpURLConnection getRequestConn() {  
  104.         return mHttpURLConn;  
  105.     }  
  106.  
  107. }  
  108.  

好了就到這裡吧,後面的待續。。。

 這一篇網絡模塊處理有些地方有待優化,優化處理部分請閱讀下篇。


轉自:http://blog.csdn.net/android_ls/article/details/8732427

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved