您的位置:首页 > 理论基础 > 计算机网络

android并发网络请求的处理

2016-03-01 10:37 567 查看
最近在做android客户端的统计sdk,为了保证数据统计的准确行,需要把一些基本信息,和无网络情况下用户的操作保存到SqlLite本地数据库中,等待有网了的时候进行传;

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

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

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

规则:

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

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

构思:

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

废话说完,上例子:

首先是封装好的Runnable

public class HttpConnRunnable implements Runnable, Parcelable {

public static final int HIGH_LEVEL = 0;

public static final int NORMAL_LEVEL = 1;

public static final int LOW_LEVEL = 2;

private int mPriority = NORMAL_LEVEL;//优先级,默认为普通

private String mUrl = "";

private HttpConnListener mListener;//监听器

public HttpConnRunnable() {

super();

}

public HttpConnRunnable(int priority) {

super();

mPriority = priority;

}

@Override

public void 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 + "-----");

}

public int getPriority() {

return mPriority;

}

public void setPriority(int priority) {

mPriority = priority;

}

public String getURL() {

return mUrl;

}

public void setURL(String url) {

mUrl = url;

}

public void setHttpConnListener(HttpConnListener listener) {

mListener = listener;

}

//序列化,为了传递给Service,如果是使用Thread处理本例,则无需序列化

public static final 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) {

return new HttpConnRunnable[size];

}

};

@Override

public int describeContents() {

return 0;

}

@Override

public void writeToParcel(Parcel dest, int flags) {

Bundle bundle = new Bundle();

bundle.putInt("PRIORITY", mPriority);

bundle.putString("URL", mUrl);

dest.writeBundle(bundle);

}

}

Service的处理:


public class HttpConnService extends Service implements HttpConnListener {

public static final String HTTP_POOL_PARAM_KEYWORD = "HttpPoolParam"; //网络参数传递的关键字

private final int HIGH_POOL_SIZE = 1;

private final int NORMAL_POOL_SIZE = 3;

private final int LOW_POOL_SIZE = 2;

// 可重用固定线程数的线程池

private ThreadPoolExecutor mHighPool;

private ThreadPoolExecutor mNormalPool;

private ThreadPoolExecutor mLowPool;

@Override

public void 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

public int 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);

}

else if (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;

}

}

return super.onStartCommand(intent, flags, startId);

}

@Override

public void onDestroy() {

mHighPool.shutdownNow();

mNormalPool.shutdownNow();

mLowPool.shutdownNow();

mNormalPool = null;

mLowPool = null;

super.onDestroy();

}

@Override

public IBinder onBind(Intent intent) {

return null;

}

@Override

public void onSucceed(String result) {

Intent intent = new Intent();

intent.setAction("com.ezstudio.connpool.HttpConnReceiver");

// 要发送的内容

intent.putExtra("RESULT", result);

// 发送 一个无序广播

sendBroadcast(intent);

}

@Override

public void onFailed() {

// TODO Auto-generated method stub

}

}

Receiver的处理比较简单:


public class HttpConnReceiver extends BroadcastReceiver {

private HttpConnListener mListener;

public void setHttpConnListener (HttpConnListener listener) {

mListener = listener;

}

@Override

public void onReceive(Context context, Intent intent) {

String action = intent.getAction();

if (action.equals("com.ezstudio.connpool.HttpConnReceiver")) {

String result = intent.getStringExtra("RESULT");

mListener.onSucceed(result);

}

}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: