在客户端用户操作后,先将数据上传到服务器再响应给用户,响应过程可能会比较慢。为了快速响应用户操作,可以先将数据存到客户端中,后面再将数据按一定时间段上传到服务器上。本文将介绍:“定义一个用于定时上传数据的类”、“在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; //随时可能有用户交班或会话超时发生
}