在android开发中我们常常会使用要异步队列来提升用户体验,如微信中的评论、赞都是采用异步队列来实现的,最近的项目产品也要这样的实现,本方法是采用HandlerThread+阻塞队列实现。
/**
* 异步网络请求模型 有队列系统,严格按照请求序列进行
*/
public class AsynTaskManager {
private static final int NEW_REQUEST = 1;
private static final int INIT_REQUEST = 2;
/**
* 重试次数
*/
public static final int MAX_RETRY_TIME = 3;
/**
*
* 出现错误后的延迟时间
*/
public static final long BASE_DELAY_MILLIS = 20000;
private BlockingQueue<AsyncProviderTask> taskQueue = new LinkedBlockingQueue<AsyncProviderTask>();
private EntityManager<AsyncProviderTask> dbManager;
private HandlerThread handlerThread;
private Handler networkHandler;
private NetworkHelper.NetworkInductor networdDector = new NetworkHelper.NetworkInductor() {
@Override
public void onNetworkChanged(NetworkHelper.NetworkStatus networkStatus) {
networkHandler.sendEmptyMessageDelayed(NEW_REQUEST, BASE_DELAY_MILLIS);
}
};
private AsynTaskManager() {
dbManager = EntityManagerFactory.getInstance(ACContext.getInstance().getApplicationContext(), 1, "useraccount", null, null).getEntityManager(AsyncProviderTask.class, null);
handlerThread = new HandlerThread("AsynTaskThread");
handlerThread.start();
networkHandler = new NetworkHandler(handlerThread.getLooper());
NetworkHelper.sharedHelper().addNetworkInductor(networdDector);
networkHandler.sendEmptyMessage(INIT_REQUEST);
}
public void submitTask(NewPostEntityProvider<?> protocol) {
AsyncProviderTask task = new AsyncProviderTask(protocol);
task.store();
saveTask(task);
taskQueue.add(task);
networkHandler.sendEmptyMessage(NEW_REQUEST);
}
private void saveTask(AsyncProviderTask task) {
dbManager.saveOrUpdate(task);
}
private void deleteTask(AsyncProviderTask task) {
WhereBuilder wherebuilder = WhereBuilder.create("taskId", "=", task.taskId);
dbManager.delete(wherebuilder);
}
public void destory() {
handlerThread.quit();
taskQueue.clear();
NetworkHelper.sharedHelper().removeNetworkInductor(networdDector);
dbManager.close();
}
private class NetworkHandler extends Handler {
/**
* 错误3次以上就开始延时重试
*/
private int errorCount = 0;
private NetworkHandler(Looper looper) {
super(looper);
}
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
switch (msg.what) {
case INIT_REQUEST:
loadAllTask();
sendEmptyMessage(NEW_REQUEST);
break;
case NEW_REQUEST:
AsyncProviderTask task = (AsyncProviderTask) msg.obj;
if (task == null) {
try {
task = taskQueue.take();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
if (task == null)
break;
// 真实发起网络请求
task.send();
if (task.isConnectToSever()) {
// 连通网络的
deleteTask(task);
task = null;
// 重置错误计数
errorCount = 0;
} else {
errorCount++;
}
removeMessages(NEW_REQUEST);
Message oldTask = obtainMessage(NEW_REQUEST, task);
if (errorCount > MAX_RETRY_TIME) {
sendMessageDelayed(oldTask, BASE_DELAY_MILLIS * errorCount);
} else {
sendMessage(oldTask);
}
break;
default:
break;
}
}
}
private void loadAllTask() {
taskQueue.clear();
Selector selector = Selector.create();
selector.orderBy("dbId", false);
List<AsyncProviderTask> tasks = dbManager.findAll(selector);
if (tasks != null) {
taskQueue.addAll(tasks);
}
}
private static class InstanceHolder {
public static AsynTaskManager manager = new AsynTaskManager();
}
public static AsynTaskManager getInstance() {
return InstanceHolder.manager;
}
}
/**
* @Description:对通用协议的包装,支持序列化把原来的协议转化成json格式存放,注意,对于每个协议中需要保存的字段(请求参数),要加上@Expose注解
*/
@Table(version = 1)
public class AsyncProviderTask extends NewPostEntityProvider {
@Id( strategy = GenerationType.AUTO_INCREMENT)
public int dbId;
@Column
public String taskId;
/**
* 用于存放协议的请求数据,暂时只支持基本数据类型
*/
@Column
public String paramJson;
@Column
public String className;
public boolean isConnectToSever() {
return reachServer;
}
public boolean reachServer;
@Column
public NewPostEntityProvider<?> innerProvider;
public AsyncProviderTask(NewPostEntityProvider<?> innerProvider)
{
super(innerProvider.getCallback());
taskId = UUID.randomUUID().toString();
this.innerProvider = innerProvider;
}
public AsyncProviderTask() {
}
public void store() {
if( innerProvider != null) {
// Map<String, String> ret = innerProvider.getParams();
Gson gson = new GsonBuilder().excludeFieldsWithoutExposeAnnotation().create();
paramJson = gson.toJson(innerProvider);
className = innerProvider.getClass().getCanonicalName();
}
}
public void load() {
if( paramJson == null || className == null) {
return;
}
Gson gson = new GsonBuilder().excludeFieldsWithoutExposeAnnotation().create();
try {
Class<?> protocolClass = Class.forName(className);
innerProvider = (NewPostEntityProvider<?>) gson.fromJson(paramJson, protocolClass);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
@Override
public boolean supportPost() {
return innerProvider.supportPost();
}
@Override
public boolean supportDesencrypt() {
return innerProvider.supportDesencrypt();
}
@Override
public String getURL() {
return innerProvider.getURL();
}
@Override
public void onResponse(String resp) {
innerProvider.onResponse(resp);
}
@Override
final public Map<String, String> getParams() {
Map<String, String> ret;
if( innerProvider == null) {
load();
}
if( innerProvider != null) {
ret = innerProvider.getParams();
return ret;
}
return super.getParams();
}
@Override
public void send() {
if( innerProvider == null) {
load();
}
send(true);
}
@Override
public void onSuccess() {
super.onSuccess();
NLog.d("TTT", "success %s",innerProvider.getClass().getCanonicalName());
innerProvider.onSuccess();
}
//这儿成功是指与服务取得了联系,至于业务上的不成功,不算重试
reachServer = true;
}
@Override
public void onCancel() {
super.onCancel();
innerProvider.onCancel();
reachServer = true;
}
@Override
public void onError(int err, int statusCode) {
super.onError(err, statusCode);
if( statusCode > 200) {
reachServer = true; //这儿成功是指与服务取得了联系,至于业务上的不成功,不算重试
}
innerProvider.onError(err, statusCode);
}
}