android并发网络请求的处理

ゝ一世哀愁。 2022-08-20 13:21 280阅读 0赞
  1. 最近在做android客户端的统计sdk,为了保证数据统计的准确行,需要把一些基本信息,和无网络情况下用户的操作保存到SqlLite本地数据库中,等待有网了的时候进行传;

基本解决思路,离线操作的数据请求URL和请求参数进行封装,封装到对象中,转化为json存储到SQlLite数据库中;定时任务检测网络情况,如果有网,则把数据库中数据取出,进行网络上传;

  1. 取出数据库中请求,就需要处理大量网络请求,同时发送请求的情况,一般来说一个网络请求都会用使用到一个异步线程,大量的线程创建、运行、销毁又造成了系统资源的浪费,而且同时同时new出多个子线程也会造成客户端卡死现象;于是考虑到能不能做个请求队列去进行控制

在这个模型中,有高中低三个优先级信道如下:高优先级—1,中优先级—3,低优先级—2

规则:

1.正常情况下各个优先级使用各自信道(线程)

2.高级信道满载、中、低级信道空置,则高级请求可使用低级信道

构思:

UI线程将期望的网络请求url和参数通过一个封装好的Runnable提交给Service处理(当然也可以交给一个Thread处理,本例使用Service),Service接收到请求,判断优先级,加入到相应线程池中排队。线程池启动线程发起网络请求,最后通过监听器将结果返回给Service,Service发送广播通知UI线程,UI线程更新相关界面,结束。

废话说完,上例子:

首先是封装好的Runnable

  1. public class HttpConnRunnable implements Runnable, Parcelable {
  2. public static final int HIGH_LEVEL = 0;
  3. public static final int NORMAL_LEVEL = 1;
  4. public static final int LOW_LEVEL = 2;
  5. private int mPriority = NORMAL_LEVEL;//优先级,默认为普通
  6. private String mUrl = “”;
  7. private HttpConnListener mListener;//监听器
  8. public HttpConnRunnable() {
  9. super();
  10. }
  11. public HttpConnRunnable(int priority) {
  12. super();
  13. mPriority = priority;
  14. }
  15. @Override
  16. public void run() {
  17. Log.i(Thread.currentThread().getName(), “——Start to connect:” + mUrl + “, priority:” + mPriority + “——-“);
  18. try {
  19. Thread.sleep(10000);
  20. //TODO:进行网络请求相关操作,并通过listener返回结果
  21. mListener.onSucceed(“Connected to “ + mUrl + “ succeed!”);
  22. }
  23. catch (InterruptedException e) {
  24. e.printStackTrace();
  25. }
  26. Log.i(Thread.currentThread().getName(), “——Finish to connect:” + mUrl + “, priority:” + mPriority + “——-“);
  27. }
  28. public int getPriority() {
  29. return mPriority;
  30. }
  31. public void setPriority(int priority) {
  32. mPriority = priority;
  33. }
  34. public String getURL() {
  35. return mUrl;
  36. }
  37. public void setURL(String url) {
  38. mUrl = url;
  39. }
  40. public void setHttpConnListener(HttpConnListener listener) {
  41. mListener = listener;
  42. }
  43. //序列化,为了传递给Service,如果是使用Thread处理本例,则无需序列化
  44. public static final Parcelable.Creator CREATOR = new Creator() {
  45. @Override
  46. public HttpConnRunnable createFromParcel(Parcel source) {
  47. HttpConnRunnable data = null;
  48. Bundle bundle = source.readBundle();
  49. if(bundle != null) {
  50. data = new HttpConnRunnable(bundle.getInt(“PRIORITY”));
  51. data.mUrl = bundle.getString(“URL”);
  52. }
  53. return data;
  54. }
  55. @Override
  56. public HttpConnRunnable[] newArray(int size) {
  57. return new HttpConnRunnable[size];
  58. }
  59. };
  60. @Override
  61. public int describeContents() {
  62. return 0;
  63. }
  64. @Override
  65. public void writeToParcel(Parcel dest, int flags) {
  66. Bundle bundle = new Bundle();
  67. bundle.putInt(“PRIORITY”, mPriority);
  68. bundle.putString(“URL”, mUrl);
  69. dest.writeBundle(bundle);
  70. }
  71. }
  1. Service的处理:
  1. public class HttpConnService extends Service implements HttpConnListener {
  2. public static final String HTTP_POOL_PARAM_KEYWORD = “HttpPoolParam”; //网络参数传递的关键字
  3. private final int HIGH_POOL_SIZE = 1;
  4. private final int NORMAL_POOL_SIZE = 3;
  5. private final int LOW_POOL_SIZE = 2;
  6. // 可重用固定线程数的线程池
  7. private ThreadPoolExecutor mHighPool;
  8. private ThreadPoolExecutor mNormalPool;
  9. private ThreadPoolExecutor mLowPool;
  10. @Override
  11. public void onCreate() {
  12. //初始化所有
  13. mHighPool = (ThreadPoolExecutor) Executors.newFixedThreadPool(HIGH_POOL_SIZE);
  14. mNormalPool = (ThreadPoolExecutor) Executors.newFixedThreadPool(NORMAL_POOL_SIZE);
  15. mLowPool = (ThreadPoolExecutor) Executors.newFixedThreadPool(LOW_POOL_SIZE);
  16. super.onCreate();
  17. }
  18. @Override
  19. public int onStartCommand(Intent intent, int flags, int startId) {
  20. //接受到来自UI线程的请求
  21. //取出Runnable,并加入到相应队列
  22. Bundle bundle = intent.getExtras();
  23. HttpConnRunnable httpConnRunnable = bundle.getParcelable(HTTP_POOL_PARAM_KEYWORD);
  24. if (httpConnRunnable != null) {
  25. httpConnRunnable.setHttpConnListener(HttpConnService.this);
  26. int level = httpConnRunnable.getPriority();
  27. switch (level) {
  28. case HttpConnRunnable.HIGH_LEVEL:
  29. //如果高级池满而低级池未满交由低级池处理
  30. //如果高级池满而普通池未满交由普通池处理
  31. //如果高级池未满则交给高级池处理,否则,交由高级池排队等候
  32. if (mHighPool.getActiveCount() == HIGH_POOL_SIZE && mLowPool.getActiveCount() < LOW_POOL_SIZE) {
  33. mLowPool.execute(httpConnRunnable);
  34. }
  35. else if (mHighPool.getActiveCount() == HIGH_POOL_SIZE && mNormalPool.getActiveCount() < NORMAL_POOL_SIZE) {
  36. mNormalPool.execute(httpConnRunnable);
  37. }
  38. else {
  39. mHighPool.execute(httpConnRunnable);
  40. }
  41. break;
  42. case HttpConnRunnable.NORMAL_LEVEL:
  43. //如果普通池满而低级池未满交由低级池处理
  44. //如果普通池未满则交给普通池处理,否则,交由普通池排队等候
  45. if (mNormalPool.getActiveCount() == NORMAL_POOL_SIZE && mLowPool.getActiveCount() < LOW_POOL_SIZE) {
  46. mLowPool.execute(httpConnRunnable);
  47. }
  48. else {
  49. mNormalPool.execute(httpConnRunnable);
  50. }
  51. break;
  52. case HttpConnRunnable.LOW_LEVEL:
  53. mLowPool.execute(httpConnRunnable);
  54. break;
  55. }
  56. }
  57. return super.onStartCommand(intent, flags, startId);
  58. }
  59. @Override
  60. public void onDestroy() {
  61. mHighPool.shutdownNow();
  62. mNormalPool.shutdownNow();
  63. mLowPool.shutdownNow();
  64. mNormalPool = null;
  65. mLowPool = null;
  66. super.onDestroy();
  67. }
  68. @Override
  69. public IBinder onBind(Intent intent) {
  70. return null;
  71. }
  72. @Override
  73. public void onSucceed(String result) {
  74. Intent intent = new Intent();
  75. intent.setAction(“com.ezstudio.connpool.HttpConnReceiver”);
  76. // 要发送的内容
  77. intent.putExtra(“RESULT”, result);
  78. // 发送 一个无序广播
  79. sendBroadcast(intent);
  80. }
  81. @Override
  82. public void onFailed() {
  83. // TODO Auto-generated method stub
  84. }
  85. }
  1. Receiver的处理比较简单:
  1. public class HttpConnReceiver extends BroadcastReceiver {
  2. private HttpConnListener mListener;
  3. public void setHttpConnListener (HttpConnListener listener) {
  4. mListener = listener;
  5. }
  6. @Override
  7. public void onReceive(Context context, Intent intent) {
  8. String action = intent.getAction();
  9. if (action.equals(“com.ezstudio.connpool.HttpConnReceiver”)) {
  10. String result = intent.getStringExtra(“RESULT”);
  11. mListener.onSucceed(result);
  12. }
  13. }
  14. }

发表评论

表情:
评论列表 (有 0 条评论,280人围观)

还没有评论,来说两句吧...

相关阅读

    相关 Android9网络请求

    手机升级了9.0,调试程序的时候发现网络请求总是失败。逛了一下CSDN发现了问题所在。 Android P 限制了明文流量的网络请求,非加密的流量请求都会被系统禁止掉。

    相关 android并发请求处理

    最近在做android统计SDK,因为之前参与的网络开发项目都遇到一些相同的问题: 1.大量的并发请求造成堵塞,特别是遇上让人无语的3G网络,无限loading。。。 2.