在客户端用户操作后,先将数据上传到服务器再响应给用户,响应过程可能会比较慢。为了快速响应用户操作,可以先将数据存到客户端中,后面再将数据按一定时间段上传到服务器上。本文将介绍:“定义一个用于定时上传数据的类”、“在AppApplication启动时,运行SyncThread同步线程”、“结束SyncThread同步线程”。
1、定义一个用于定时上传数据的类。
public class SyncThread extends Thread
SyncThread继承于Thread,是一个线程类,在run方法中进行定时上传数据:
查看代码
@Override
public void run() {
EventBus.getDefault().register(this);//在线程运行后才注册EventBus
while (atomicInteger.get() != SIGNAL_ThreadExit) {
while (aiPause.get() == PAUSE && atomicInteger.get() != SIGNAL_ThreadExit) {
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
if (atomicInteger.get() == SIGNAL_ThreadExit) {
break; //在断网情况下,staff登录到的是本地SQLite,本线程不会被启动。退出登录后,下面的代码不需要执行,所以这里break出去。同时,随时可能有用户交班或会话超时发生
}
//定时批量上传零售单:第一次上传时间的5秒后,查询本地SQLite是否存在临时零售单,若存在,进行批量上传。每一次进行零售单的上传,都要把lastCreateNRetailtradeTime设置成最近上传完成的时间
int iTimeout = 10; //10* 500 = 5秒
while (iTimeout-- > 0 && atomicExecuteInstantly.get() != 1) {
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
if (atomicInteger.get() == SIGNAL_ThreadExit) {
break; //随时可能有用户交班或会话超时发生
}
}
if (atomicExecuteInstantly.get() == 1) {
atomicExecuteInstantly.set(0);
}
if (atomicInteger.get() == SIGNAL_ThreadExit) {
break; //随时可能有用户交班或会话超时发生
}
queryLocalRetailTradeAndUpload();//TODO 交班或会话超时之时,UI层切换activity可能会慢,以后需要waiting dialog。
}
log.info("线程:" + this.getName() + "正常结束");
}
private void queryLocalRetailTradeAndUpload() {
//查找本地是否存在临时零售单,并且上传
log.info("同步线程开始查找临时零售单!");
retrieveNTempRetailTradeInSQLite();
}
/**
* 找到本地所有的临时RetailTrade,并上传
*/
public boolean retrieveNTempRetailTradeInSQLite() {
retailTradeHttpEvent.setStatus(BaseEvent.EnumEventStatus.EES_Http_ToDo);
retailTradeSQLiteEvent.setStatus(BaseEvent.EnumEventStatus.EES_SQLite_ToDo);
retailTradeSQLiteEvent.setEventTypeSQLite(BaseSQLiteEvent.EnumSQLiteEventType.ESET_RetailTrade_RetrieveNAsync);
if (!retailTradeSQLiteBO.retrieveNASync(BaseSQLiteBO.CASE_RetailTrade_RetrieveNToUpload, null)) {
log.info("查询临时零售单失败!");
}
long lTimeOut = 60;
while (retailTradeSQLiteEvent.getStatus() != BaseEvent.EnumEventStatus.EES_SQLite_DoneApplyServerData && lTimeOut-- > 0) {
if ((retailTradeSQLiteEvent.getStatus() == BaseEvent.EnumEventStatus.EES_SQLite_Done && retailTradeSQLiteEvent.getLastErrorCode() != ErrorInfo.EnumErrorCode.EC_NoError)//因为是在Presenter中设置了错误码,在event中设置了状态,所以先判断状态再判断错误码
|| (retailTradeHttpEvent.getStatus() == BaseEvent.EnumEventStatus.EES_Http_Done && retailTradeHttpEvent.getLastErrorCode() != ErrorInfo.EnumErrorCode.EC_NoError)) {
break;
}
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
if (retailTradeHttpEvent.getStatus() == BaseEvent.EnumEventStatus.EES_Http_Done && retailTradeHttpEvent.getLastErrorCode() != ErrorInfo.EnumErrorCode.EC_NoError) {
log.error("解析服务器返回的RetailTrade出错!");
return false;
}
if (lTimeOut <= 0) {
log.error("上传临时零售单同步数据失败!原因:超时!");
log.error("创建retailtrade失败");// TODO 将来可能添加处理
retailTradeHttpEvent.setLastErrorCode(ErrorInfo.EnumErrorCode.EC_NoError);
return false;
} else {
return true;
}
}
2、在AppApplication启动时,运行SyncThread同步线程。
/**
* 启动同步线程。如果已经启动,就不重新启动。
*/
public void startSyncThread() {
if (syncThread == null) {
syncThread = new SyncThread(10L);
SyncThread.aiPause.set(SyncThread.RESUME);
// SyncThread.aiPause.set(SyncThread.PAUSE);
syncThread.start();
logger.info("同步线程已经启动。线程在运行状态。");
} else {
logger.debug("同步线程已经在运行中,不需要再启动");
}
}
3、结束SyncThread同步线程。
/**
* 什么时候退出?1、会话过期。2、交班
*/
public void exitFromSyncThread() {
logger.debug("准备关闭同步线程");
if (syncThread != null) {
//退出同步线程
syncThread.exit();
try {
syncThread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
syncThread = null;
logger.info("同步线程已经结束");
} else {
System.out.println("同步线程为null,应该是之前已经退出过");
}
}
public void exit() {
EventBus.getDefault().unregister(this);//注销EventBus
atomicInteger.set(SIGNAL_ThreadExit);
aiPause.set(RESUME);
}
SyncThread类的run方法中判断atomicInteger.get() == SIGNAL_ThreadExit时,跳出循环,结束上传数据。
if (atomicInteger.get() == SIGNAL_ThreadExit) {
break; //随时可能有用户交班或会话超时发生
}