android併發網路請求的處理
阿新 • • 發佈:2019-02-12
最近在做android客戶端的統計sdk,為了保證資料統計的準確行,需要把一些基本資訊,和無網路情況下使用者的操作儲存到SqlLite本地資料庫中,等待有網了的時候進行傳;
基本解決思路,離線操作的資料請求URL和請求引數進行封裝,封裝到物件中,轉化為json儲存到SQlLite資料庫中;定時任務檢測網路情況,如果有網,則把資料庫中資料取出,進行網路上傳;
取出資料庫中請求,就需要處理大量網路請求,同時傳送請求的情況,一般來說一個網路請求都會用使用到一個非同步執行緒,大量的執行緒建立、執行、銷燬又造成了系統資源的浪費,而且同時同時new出多個子執行緒也會造成客戶端卡死現象;於是考慮到能不能做個請求佇列去進行控制
-
public
- publicstaticfinalint HIGH_LEVEL = 0;
- publicstaticfinalint NORMAL_LEVEL = 1;
- publicstaticfinalint LOW_LEVEL = 2;
- privateint mPriority = NORMAL_LEVEL;//優先順序,預設為普通
- private String mUrl = "";
-
private HttpConnListener mListener;
- public HttpConnRunnable() {
- super();
- }
- public HttpConnRunnable(int priority) {
- super();
- mPriority = priority;
- }
- @Override
- publicvoid run() {
- Log.i(Thread.currentThread().getName(), "----Start to connect:" + mUrl + ", priority:" + mPriority + "-----");
- try {
- Thread.sleep(10000);
- //TODO:進行網路請求相關操作,並通過listener返回結果
- mListener.onSucceed("Connected to " + mUrl + " succeed!");
- }
- catch (InterruptedException e) {
- e.printStackTrace();
- }
- Log.i(Thread.currentThread().getName(), "----Finish to connect:" + mUrl + ", priority:" + mPriority + "-----");
- }
- publicint getPriority() {
- return mPriority;
- }
- publicvoid setPriority(int priority) {
- mPriority = priority;
- }
- public String getURL() {
- return mUrl;
- }
- publicvoid setURL(String url) {
- mUrl = url;
- }
- publicvoid setHttpConnListener(HttpConnListener listener) {
- mListener = listener;
- }
- //序列化,為了傳遞給Service,如果是使用Thread處理本例,則無需序列化
- publicstaticfinal Parcelable.Creator CREATOR = new Creator() {
- @Override
- public HttpConnRunnable createFromParcel(Parcel source) {
- HttpConnRunnable data = null;
- Bundle bundle = source.readBundle();
- if(bundle != null) {
- data = new HttpConnRunnable(bundle.getInt("PRIORITY"));
- data.mUrl = bundle.getString("URL");
- }
- return data;
- }
- @Override
- public HttpConnRunnable[] newArray(int size) {
- returnnew HttpConnRunnable[size];
- }
- };
- @Override
- publicint describeContents() {
- return0;
- }
- @Override
- publicvoid writeToParcel(Parcel dest, int flags) {
- Bundle bundle = new Bundle();
- bundle.putInt("PRIORITY", mPriority);
- bundle.putString("URL", mUrl);
- dest.writeBundle(bundle);
- }
- }
Service的處理:
- publicclass HttpConnService extends Service implements HttpConnListener {
- publicstaticfinal String HTTP_POOL_PARAM_KEYWORD = "HttpPoolParam"; //網路引數傳遞的關鍵字
- privatefinalint HIGH_POOL_SIZE = 1;
- privatefinalint NORMAL_POOL_SIZE = 3;
- privatefinalint LOW_POOL_SIZE = 2;
- // 可重用固定執行緒數的執行緒池
- private ThreadPoolExecutor mHighPool;
- private ThreadPoolExecutor mNormalPool;
- private ThreadPoolExecutor mLowPool;
- @Override
- publicvoid onCreate() {
- //初始化所有
- mHighPool = (ThreadPoolExecutor) Executors.newFixedThreadPool(HIGH_POOL_SIZE);
- mNormalPool = (ThreadPoolExecutor) Executors.newFixedThreadPool(NORMAL_POOL_SIZE);
- mLowPool = (ThreadPoolExecutor) Executors.newFixedThreadPool(LOW_POOL_SIZE);
- super.onCreate();
- }
- @Override
- publicint onStartCommand(Intent intent, int flags, int startId) {
- //接受到來自UI執行緒的請求
- //取出Runnable,並加入到相應佇列
- Bundle bundle = intent.getExtras();
- HttpConnRunnable httpConnRunnable = bundle.getParcelable(HTTP_POOL_PARAM_KEYWORD);
- if (httpConnRunnable != null) {
- httpConnRunnable.setHttpConnListener(HttpConnService.this);
- int level = httpConnRunnable.getPriority();
- switch (level) {
- case HttpConnRunnable.HIGH_LEVEL:
- //如果高階池滿而低階池未滿交由低階池處理
- //如果高階池滿而普通池未滿交由普通池處理
- //如果高階池未滿則交給高階池處理,否則,交由高階池排隊等候
- if (mHighPool.getActiveCount() == HIGH_POOL_SIZE && mLowPool.getActiveCount() < LOW_POOL_SIZE) {
- mLowPool.execute(httpConnRunnable);
- }
- elseif (mHighPool.getActiveCount() == HIGH_POOL_SIZE && mNormalPool.getActiveCount() < NORMAL_POOL_SIZE) {
- mNormalPool.execute(httpConnRunnable);
- }
- else {
- mHighPool.execute(httpConnRunnable);
- }
- break;
- case HttpConnRunnable.NORMAL_LEVEL:
- //如果普通池滿而低階池未滿交由低階池處理
- //如果普通池未滿則交給普通池處理,否則,交由普通池排隊等候
- if (mNormalPool.getActiveCount() == NORMAL_POOL_SIZE && mLowPool.getActiveCount() < LOW_POOL_SIZE) {
- mLowPool.execute(httpConnRunnable);
- }
- else {
- mNormalPool.execute(httpConnRunnable);
- }
- break;
- case HttpConnRunnable.LOW_LEVEL:
- mLowPool.execute(httpConnRunnable);
- break;
- }
- }
- returnsuper.onStartCommand(intent, flags, startId);
- }
- @Override
- publicvoid onDestroy() {
- mHighPool.shutdownNow();
- mNormalPool.shutdownNow();
- mLowPool.shutdownNow();
- mNormalPool = null;
- mLowPool = null;
- super.onDestroy();
- }
- @Override
- public IBinder onBind(Intent intent) {
- returnnull;
- }
- @Override
- publicvoid onSucceed(String result) {
- Intent intent = new Intent();
- intent.setAction("com.ezstudio.connpool.HttpConnReceiver");
- // 要傳送的內容
- intent.putExtra("RESULT", result);
- // 傳送 一個無序廣播
- sendBroadcast(intent);
- }
- @Override
- publicvoid onFailed() {
- // TODO Auto-generated method stub
- }
- }
Receiver的處理比較簡單:
- publicclass HttpConnReceiver extends BroadcastReceiver {
- private HttpConnListener mListener;
- publicvoid setHttpConnListener (HttpConnListener listener) {
- mListener = listener;
- }
- @Override
- publicvoid onReceive(Context context, Intent intent) {
- String action = intent.getAction();
- if (action.equals("com.ezstudio.connpool.HttpConnReceiver")) {
- String result = intent.getStringExtra("RESULT");
- mListener.onSucceed(result);
- }
- }
- }